0

I am trying to pass some values that I get with a select * query through a method. I get a NullPointerException. This is my log:

FATAL EXCEPTION: main
    Process: dominio.android.forca, PID: 32241
    java.lang.RuntimeException: Unable to start activity ComponentInfo{dominio.android.forca/dominio.android.forca.JogoAct}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List dominio.android.forca.data.AddressBookDatabaseHelper.Exemplo()' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2426)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490)
        at android.app.ActivityThread.-wrap11(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:148)
        at android.app.ActivityThread.main(ActivityThread.java:5443)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
      Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List dominio.android.forca.data.AddressBookDatabaseHelper.Exemplo()' on a null object reference
        at dominio.android.forca.data.Palavras.sorteio(Palavras.java:67)
        at dominio.android.forca.JogoAct.iniciarJogo(JogoAct.java:195)
        at dominio.android.forca.JogoAct.onCreate(JogoAct.java:39)
        at android.app.Activity.performCreate(Activity.java:6245)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1130)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2379)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2490) 
        at android.app.ActivityThread.-wrap11(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1354) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:148) 
        at android.app.ActivityThread.main(ActivityThread.java:5443) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

This is the class that I need to receive the select * data:

public class Palavras extends ContentProvider {
    private String[] palavras;

    private List<String> lista_palavras;

    public Palavras() {

    }

    // used to access the database
    private AddressBookDatabaseHelper dbHelper;


    @Override
    public boolean onCreate() {
        // create the AddressBookDatabaseHelper
        dbHelper = new AddressBookDatabaseHelper(getContext());
        return true; // ContentProvider successfully created
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Cursor query(Uri uri, String[] projection,
                        String selection, String[] selectionArgs, String sortOrder) {

        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }

    public String sorteio() {


        //lista_palavras = dbHelper.Exemplo();
        //String palavraSorteada = lista_palavras.get((int)(random()*lista_palavras.size()));

        palavras = dbHelper.Exemplo2();

        String palavraSorteada = palavras[(int)(random()*palavras.length)];

        return palavraSorteada;
    }

    public static double random() {
        Random r = new Random();

        return r.nextDouble();
    }
}

This is the function that creates the database and selects a column:

class AddressBookDatabaseHelper extends SQLiteOpenHelper {
    private static final String DATABASE_NAME = "Forca.db";
    private static final int DATABASE_VERSION = 1;

    // constructor
    public AddressBookDatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }


    // creates the contacts table when the database is created
    @Override
    public void onCreate(SQLiteDatabase db) {
        // SQL for creating the contacts table
        final String CREATE_CONTACTS_TABLE =
                "CREATE TABLE " + Contact.TABLE_NAME + "(" +
                        Contact._ID + " integer primary key, " +
                        Contact.COLUMN_WORD + " TEXT, " +
                        Contact.COLUMN_TIP + " TEXT);";
        db.execSQL(CREATE_CONTACTS_TABLE); // create the contacts table
    }

    // normally defines how to upgrade the database when the schema changes
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }

    // SELECT COLUMN_WORD through a list
    public List<String> Exemplo(){
        List<String> dados = new ArrayList();
        SQLiteDatabase db = getReadableDatabase();
        String selectQuery = "SELECT palavra FROM palavrasforca";
        Cursor cursor = db.rawQuery(selectQuery, null);

        if (cursor.moveToFirst()) {
            do{
                String palavra = cursor.getString(cursor.getColumnIndex("palavra"));
                dados.add(palavra);
            }while (cursor.moveToNext());
        }

        return dados;
        //aqui dados terá todos os valores do banco
    }

}

This is my AndroidManifest.xml file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="dominio.android.forca">

    <application
        android:allowBackup="true"
        android:icon="@drawable/clown"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme.NoActionBar">
        <activity android:name=".PlayerAct">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".JogoAct" />
        <activity android:name=".InserirPalavraAct" />
        <activity android:name=".MainActivity" />

        <provider
            android:name=".data.AddressBookContentProvider"
            android:authorities="dominio.android.forca.data"
            android:enabled="true"
            android:exported="false"></provider>

        <activity android:name=".Autores"></activity>
    </application>

</manifest>

This is where I called sorteio() in my JogoAct class:

import dominio.android.forca.data.Palavras;
import dominio.android.forca.data.Replace;

public class JogoAct extends AppCompatActivity implements View.OnClickListener {


    Palavras palavras = new Palavras();

    private String palavraSecreta, tracos;
    private int nTentativas;
    private char letra;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jogo);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        txtDica = (TextView)findViewById(R.id.txtDica);
        iniciarObjetos();
        iniciarJogo();

    }

   public void iniciarJogo() {
        palavraSecreta = palavras.sorteio(); // <<<<< HERE
        nTentativas = 6;
        tracos = "";
        letra = ' ';
        for (int x = 0; x < palavraSecreta.length(); x++) {
            if (palavraSecreta.charAt(x) == '-') {
                tracos += " - ";
            }
            else if(palavraSecreta.charAt(x) == ' '){
                tracos += "   ";
            }
            else {
                tracos += " _ ";
            }
        }

        habilitarBotoes();
        tvPalavra.setText(tracos);
        forca.setImageResource(R.drawable.forca_6);
    }

Why am I getting this error? Any suggestions?

Razor
  • 1,778
  • 4
  • 19
  • 36
  • looks like you are calling the methods on the content provider directly, instead of using it as a contentprovider – njzk2 Jun 14 '16 at 21:29
  • sorry, but what do you mean? – Vinícius Avansini Jun 14 '16 at 21:36
  • So, the error is occuring in sorteio() but how is that getting called? Also, post your AndroidManifest.xml file. Did you forget to add the content provider? – iheanyi Jun 14 '16 at 22:34
  • Sorry, I am newbe on Android development! So I updated the post as can you see. About content provider, I don't know how to add this. I read a lot of posts but I don't really understand how to implement this. Can you help me? – Vinícius Avansini Jun 14 '16 at 22:56

1 Answers1

0

According to Documentation of ContentProvider constructor: ContentProvider () Construct a ContentProvider instance. Content providers must be declared in the manifest, accessed with ContentResolver, and created automatically by the system, so applications usually do not create ContentProvider instances directly. At construction time, the object is uninitialized, and most fields and methods are unavailable. Subclasses should initialize themselves in onCreate(), not the constructor. Content providers are created on the application main thread at application launch time. The constructor must not perform lengthy operations, or application startup will be delayed.

So I think the main reason is your DBHelper has not initialized yet, it currently is null. So your call will throw exception.

To access the Provider, try through ContentResolver.

You can follow this tutorial to learn about ContentProvider and how to access it through ContentResolver

Android SQLite database and content provider

Hope it help !

Alex Hong
  • 281
  • 1
  • 11