Search code examples
javaandroidsqliteandroid-context

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!


Solution

  • 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.