DWA
DWA

Reputation: 530

Passing the right App Context to the Database Handler fails

I am working on an Android App with a Database and I am having troubles in passing the right context to my Database Handler, as the instance of the App Context that I am passing to the Database Handler seems to be always null; as I have been working on this for hours to make it work, I would appreciate any hints or constructive Feedback to make this work.

The app crashes always with the same Null Pointer Exception:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.rawQuery(java.lang.String, java.lang.String[])' on a null object reference 

in the method DatabaseHandler.getAllItems, at this part:

 try (SQLiteDatabase db = this.getWritableDatabase(GoldbekStorageApp.getInstance())) {
            cursor = db.rawQuery(selectQuery, null);
        } 

This is my Database Handler:

enter code herepackage com.example.xxx;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;


public class DatabaseHandler extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 2;
    private static final String DATABASE_NAME = "itemsManager";
    private static final String TABLE_ITEMS = "items";
    private static final String KEY_NO = "number";
    private static final String TAG = "Database values";
    private static final String KEY_NAME = "name";
    private static final String KEY_EAN = "ean";
    private static final String KEY_TYPE = "type";
    private static final String KEY_ITEMGROUPNAME = "itemgroupname";
    private static final String KEY_DESTRUCTION = "destruction";
    private static final String KEY_ARCHIVED = "archived";
    public static final String TAGGGG = "Datenbank" ;
    private String No;
    private String Ean;
    private String Name;
    private String Itemgroupname;
    private String Type;
    private Boolean Destruction;
    private Boolean Archived;
    public Context context;
    public String uname;


    public DatabaseHandler(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        //3rd argument to be passed is CursorFactory instance
        this.context = context; // add this line to initialize your context.
    }


    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {
        String CREATE_ITEMS_TABLE = "CREATE TABLE " + TABLE_ITEMS + "("
                + KEY_NO + " TEXT ," + KEY_NAME + " TEXT,"
                + KEY_ITEMGROUPNAME + " TEXT,"
                + KEY_TYPE + " TEXT,"
                + KEY_EAN + " TEXT,"
                + KEY_DESTRUCTION + " BOOLEAN,"
                + KEY_ARCHIVED + " BOOLEAN" +")";
        Log.d(TAG, CREATE_ITEMS_TABLE);
        db.execSQL(CREATE_ITEMS_TABLE);
    }

    public boolean getItemByEAN(String code) {

        SQLiteDatabase db = this.getWritableDatabase();
       Cursor mCursor = db.rawQuery("SELECT * FROM items WHERE ean =?", new String[]{ Ean });

        if (mCursor != null)
        {
            Log.d(TAGGGG, "Worked");
            return true;
            /* record exist */
        }
        else
        {
            Log.d(TAGGGG, "Did not worked");
            return false;
            /* record not exist */
        }
  }

    public void checkItemAgainstDatabase(String code)
    {
        String selectQuery = "SELECT  * FROM " + TABLE_ITEMS + " WHERE " + KEY_EAN + "='" + code + "'";
        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list

        if(cursor == null)
        {
            Log.d(TAGGGG, "Cursor ist Null, Item not present");
            return;
        }
        if (cursor.getCount() == 0) {
            Log.d(TAGGGG, " Item not present");
        } else {
            Log.d(TAGGGG, " Item present");
        }
        db.close();
        return;
        /*
            for (Item item : itemList) {
                String itemEanToBeMatched = item.getEan();
                if (itemEanToBeMatched.equals(code)) {
                    Toast.makeText(Context, code, Toast.LENGTH_LONG).show();
                    //ScanService.checkEnteredCode(code, code, content, mContext.getApplicationContext());
                }
                String itemNoToBeMatched = item.getNo();
                if (itemNoToBeMatched.equals(code)) {
                    Toast.makeText(mContext, code, Toast.LENGTH_LONG).show();
                    //ScanService.checkEnteredCode(code, code, content, mContext.getApplicationContext());
                }
                else {
                    Toast.makeText(mContext, R.string.not_in_database, Toast.LENGTH_LONG).show();
                    Vibrator vibrator;
                    vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
                    vibrator.vibrate(3000);
                    Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
                    Ringtone r = RingtoneManager.getRingtone(mContext.getApplicationContext(), notification);
                    r.play();
                    break;
                }
            } */
        }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_ITEMS);
        // Create tables again
        onCreate(db);
    }

    // code to add the new item
    public void addItem(Item items) {

        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_NO, ""+items.getNo()); // Item Ean
        values.put(KEY_EAN, ""+items.getEan()); // Item Ean
        values.put(KEY_NAME, items.getName()); // Item Name
        values.put(KEY_TYPE, items.getType());
        //values.put(KEY_ITEMGROUPNAM, item.getItemgroupname()); // Item Groupname
        values.put(String.valueOf(KEY_ARCHIVED), items.getArchived());
        values.put(String.valueOf(KEY_DESTRUCTION), items.getDestruction());
        // Inserting Row
        db.insert(TABLE_ITEMS, null, values);
        //2nd argument is String containing nullColumnHack
        db.close(); // Closing database connection
    }

    // code to get the single contact
    public Item getItem(int id) {
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.query(TABLE_ITEMS, new String[] { KEY_NO,
                        KEY_NAME, KEY_EAN,KEY_TYPE, String.valueOf(KEY_ARCHIVED),
                        String.valueOf(KEY_DESTRUCTION)}, KEY_NO + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();

        Item item = new Item(cursor.getString(0),
                cursor.getString(1), cursor.getString(2),
                cursor.getString(3),cursor.getString(4),cursor.getExtras().getBoolean(String.valueOf(5)),
                Boolean.getBoolean(String.valueOf(6)));
        Log.d(TAGGGG, String.valueOf(item));
        // return contact
        return item;
    }

    // code to get all contacts in a list view
    public List<Item> getAllItems(Context context) {
        List<Item> itemList = new List<Item>() {
            @Override
            public int size() {
                return 0;
            }

            @Override
            public boolean isEmpty() {
                return false;
            }

            @Override
            public boolean contains(@Nullable @org.jetbrains.annotations.Nullable Object o) {
                return false;
            }

            @NonNull
            @NotNull
            @Override
            public Iterator<Item> iterator() {
                return null;
            }

            @NonNull
            @NotNull
            @Override
            public Object[] toArray() {
                return new Object[0];
            }

            @NonNull
            @NotNull
            @Override
            public <T> T[] toArray(@NonNull @NotNull T[] a) {
                return null;
            }

            @Override
            public boolean add(Item item) {
                return false;
            }

            @Override
            public boolean remove(@Nullable @org.jetbrains.annotations.Nullable Object o) {
                return false;
            }

            @Override
            public boolean containsAll(@NonNull @NotNull Collection<?> c) {
                return false;
            }

            @Override
            public boolean addAll(@NonNull @NotNull Collection<? extends Item> c) {
                return false;
            }

            @Override
            public boolean addAll(int index, @NonNull @NotNull Collection<? extends Item> c) {
                return false;
            }

            @Override
            public boolean removeAll(@NonNull @NotNull Collection<?> c) {
                return false;
            }

            @Override
            public boolean retainAll(@NonNull @NotNull Collection<?> c) {
                return false;
            }

            @Override
            public void clear() {

            }

            @Override
            public boolean equals(@Nullable @org.jetbrains.annotations.Nullable Object o) {
                return false;
            }

            @Override
            public int hashCode() {
                return 0;
            }

            @Override
            public Item get(int index) {
                return null;
            }

            @Override
            public Item set(int index, Item element) {
                return null;
            }

            @Override
            public void add(int index, Item element) {

            }

            @Override
            public Item remove(int index) {
                return null;
            }

            @Override
            public int indexOf(@Nullable @org.jetbrains.annotations.Nullable Object o) {
                return 0;
            }

            @Override
            public int lastIndexOf(@Nullable @org.jetbrains.annotations.Nullable Object o) {
                return 0;
            }

            @NonNull
            @NotNull
            @Override
            public ListIterator<Item> listIterator() {
                return null;
            }

            @NonNull
            @NotNull
            @Override
            public ListIterator<Item> listIterator(int index) {
                return null;
            }

            @NonNull
            @NotNull
            @Override
            public List<Item> subList(int fromIndex, int toIndex) {
                return null;
            }
        };
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE_ITEMS;

        Cursor cursor;
        try (SQLiteDatabase db = this.getWritableDatabase(GoldbekStorageApp.getInstance())) {
            cursor = db.rawQuery(selectQuery, null);
        }

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                Item item = new Item(No, Name, Itemgroupname, Ean, Type, Destruction, Archived);
                item.setNo(cursor.getString(0));
                item.setName(cursor.getString(1));
                item.setEan(cursor.getString(2));
                item.setType(cursor.getString(2));
                // Adding items to list
                itemList.add(item);
            } while (cursor.moveToNext());
        }

        // return contact list
        return itemList;
    }

    private SQLiteDatabase getWritableDatabase(GoldbekStorageApp context) {
        return null;
    }

    // code to update the single item
    public int updateItem(Item item) {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(KEY_NO, item.getNo());
        values.put(KEY_NAME, item.getName());
        values.put(KEY_EAN, item.getEan());
        values.put(KEY_ITEMGROUPNAME, item.getItemgroupname());
        values.put(KEY_TYPE, item.getType());
        values.put(String.valueOf(KEY_DESTRUCTION), item.getDestruction());
        values.put(String.valueOf(KEY_ARCHIVED), item.getArchived());

        // updating row
        return db.update(TABLE_ITEMS, values, KEY_NO + " = ?",
                new String[] { String.valueOf(item.getNo()) });
    }

    // Deleting single item
    public void deleteItem(Item item) {
        SQLiteDatabase db = this.getWritableDatabase();
        db.delete(TABLE_ITEMS, KEY_NO + " = ?",
                new String[] { String.valueOf(item.getNo()) });
        db.close();
    }

    // Getting items Count
    public int getItemsCount() {
        String itemQuery = "SELECT  * FROM " + TABLE_ITEMS;
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery(itemQuery, null);
        cursor.close();
        // return count
        return cursor.getCount();
    }

}

This is my onCreate-Method in the MainActivity, where I am calling the

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Sentry.captureMessage("testing SDK setup");
        setContentView(R.layout.activity_main);
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getPosts();

//In the following lines, I am initializing the Context of my App and passing it //to the Database Handler and the Method Call of the method in the Database //Handler

    *mContext = GoldbekStorageApp.getInstance();
    DatabaseHandler db = new DatabaseHandler(mContext);
    List<Item> items = db.getAllItems(mContext);*


  new LongOperation().execute();
    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(R.id.nav_palette,
            R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
            .setDrawerLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

}

This is how I define the context of the App:

import android.app.Application;
import android.content.Context;

public class GoldbekStorageApp extends Application {

    private static Context mContext;

    public static GoldbekStorageApp mInstance= null;
    public String palNo;

    public String getPalNo() {
        return palNo;
    }

    public void setPalNo(String palNo) {
        this.palNo = palNo;
    }

    public GoldbekStorageApp(){}

    public static synchronized GoldbekStorageApp getInstance() {
        if(null == mInstance){
            mInstance = new GoldbekStorageApp();
        }
        return mInstance;
    }
}

I have the slight feeling that I am failing to initialize and pass the App Context to the Database Handler, but I don´t have the slightest idea where I am failing and what´s going wrong, as I am not an expert in handling the Context in Android; hence, any hints or help would be appreciated, thanks!

Upvotes: 1

Views: 380

Answers (3)

Dan Baruch
Dan Baruch

Reputation: 1093

You need to change your getInstance method and Ctor in GoldbekStorageApp to:

public static synchronized GoldbekStorageApp getInstance(Context con) {
    if(null == mInstance){
        mInstance = new GoldbekStorageApp(con);
    }
    return mInstance;
}

    public GoldbekStorageApp(Context con){mContext = con}

Do note, I am not sure why, I just know I've read in several places that holding a static reference to the app Context is not recommended. The first time you are calling getInstance you need to make sure you are passing a valid context (i.e getApplicationContext() or MainActivity.this or something of the sort) later calls can be made with passing null as parameter since it will be ignored anyway

Upvotes: 1

Sergey Glotov
Sergey Glotov

Reputation: 20346

First, don't create Application object. This is done by Android.
Static way to get 'Context' in Android?

Second, do you really need it? Activity has context. It is Context, in fact. If you need application context, then activity has getApplicationContext() method

Upvotes: 1

laalto
laalto

Reputation: 152827

It's not the Context.

Instead you should remove this method:

private SQLiteDatabase getWritableDatabase(GoldbekStorageApp context) {
    return null;
}

and just use SQLiteOpenHelper#getWritableDatabase() - it does not return nulls, and you pass a Context to it in the class's constructor.

There are a number of other problems with the code, this is a reason for the NPE when trying to invoke rawQuery() on null.

Upvotes: 2

Related Questions