Following my last post i was using SQLiteOpenHelper to access a pre-populated sqlite database and someone suggested i use SQLAssetHelper so i found a guide followed it and tried to implement it but i am still getting errors.
like: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
I know what a null pointer exception is in most cases but dont understand it in this context as i am new to android development. The errors on line 26 of my DBHleper class below. - String dbPath = myContext.getDatabasePath(DATABASE_NAME).getPath();
public class DBHelper extends SQLiteAssetHelper {
private static final String DATABASE_NAME = "Database.db";
private static final int DATABASE_VERSION = 1;
private Context myContext;
private SQLiteDatabase mDatabase;
public DBHelper(Context context){
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
public void openDatabase(){
String dbPath = myContext.getDatabasePath(DATABASE_NAME).getPath();
if(mDatabase!= null && mDatabase.isOpen()){
return;
}
mDatabase = SQLiteDatabase.openDatabase(dbPath,null,SQLiteDatabase.OPEN_READWRITE);
}
public Cursor getItems(){
SQLiteDatabase db = getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables("Attraction");
Cursor c = qb.query(db,null,null,null,null,null,null);
c.moveToFirst();
return c;
}
}
My main
public class MainActivity extends AppCompatActivity {
DBHelper newDB;
private Cursor attraction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
newDB = new DBHelper(this);
newDB.openDatabase();
attraction = newDB.getItems();
}
}
I am probably having a mental block and not seeing the solution but any more help on this issue will be appreciated.
Related
What's the problem that my db is null?
there says Cursor cursor = myDb.getData(select * from Donation_Details); myDb : null and it pops out the error below.
And here is the runtime error says
Here is the DatabaseHelper which When I assign & declear database.
private static final String DATABASE_NAME = "eBossCharity.db";
private static final int DATABASE_VERSION = 1;
public dbOpenHelper(Context context){
super(context,DATABASE_NAME,null,DATABASE_VERSION);
}
Here is the dbAccess when I want to get data from database.
public dbOpenHelper openHelper;
public SQLiteDatabase db;
private static dbAccess instance;
public dbAccess(Context context) {
this.openHelper = new dbOpenHelper(context);
}
public static dbAccess getInstance(Context context) {
if (instance == null) {
instance = new dbAccess(context);
}
return instance;
}
public Cursor getData(String sql) {
db = openHelper.getReadableDatabase();
return db.rawQuery("", null);
}
Here is the Summary page when I want to show the data into the customize list view. I put a break point at line 13 and debug it. It says my database is null. I Called the dbAccess method getData and grab the database"Donation_details". It should show the data...
ListView listView;
ArrayList<Model> mList;
RecordListAdapter mAdapter = null;
dbAccess myDb;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_summary__page);
this.listView = findViewById(R.id.listView);
mList = new ArrayList<>();
mAdapter = new RecordListAdapter(this,R.layout.row,mList);
listView.setAdapter(mAdapter);
Cursor cursor = myDb.getData("Select * from Donation_Details");
mList.clear();
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String txnno = cursor.getString(1);
String name = cursor.getString(2);
String txndate = cursor.getString(3);
BigDecimal amount = BigDecimal.valueOf(cursor.getDouble(4));
String description1 = cursor.getString(5);
String createddate = cursor.getString(7);
mList.add(new Model(id,txnno,name,txndate,amount,description1,createddate));
}
I think I missed something here and there. But I couldn't find it, Or maybe I typed wrong something to cause database is null? Can I have some guidance? Thank in advance...
You need to initialize 'dbAccess myDb'
Solution:
Write this
myDb = new dbAccess(this);
In your onCreate () after the line setContentView(...)
Try it..
I would like to ask anyone to please help me to modify my database connection code. What I have now is it's a part of one of my method class and it will make a connection every time I call it ( which I know its very inefficient). But when I try to move the connection part out from the method it breaks the code. I just wonder if I could make a static class somewhere so I can reuse it in other method as well.
Thanks so much for any help in advance, it is really appreciated.
Here is the method code:
public void getListDetail(){
//listDetailData.clear();
ShoppingListDatabase databaseConnection = new ShoppingListDatabase(this);
final SQLiteDatabase db = databaseConnection.open();
final ArrayList<ShoppingItem> lists = ShoppingListItemTable.selectAllItems(db, selectedID);
databaseConnection.close();
//create a list adapter and set adapter
ShoppingListItemAdapter adapter = new ShoppingListItemAdapter(this, R.layout.activity_item_detail_list, lists);
ListView_ListDetail = findViewById(R.id.ListView_ListDetail);
ListView_ListDetail.setAdapter(adapter);
adapter.notifyDataSetChanged();
// ((ArrayAdapter<String>)ListView_ListDetail.getAdapter()).notifyDataSetChanged();
}
Database class:
package com.puyakul.prin.psychic_shopping;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.ContactsContract;
import android.util.Log;
public class ShoppingListDatabase {
private static final String TAG = "ShoppingListDatabase";
private static final String DATABASE_NAME = "ShoppingListDatabase";
private static final int DATABASE_VERSION = 3;
private SQLiteDatabase mDb;
private DatabaseHelper mDbHealper;
private final Context mCtx;
public ShoppingListDatabase(Context ctx){
this.mCtx = ctx;
}
/**
* DatabaseHelper class.
*
* Database helper class to manage connections with the database.
*/
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "DatabaseHelper onCreate");
db.execSQL(ShoppingListItemTable.CREATE_STATEMENT);
db.execSQL(ShoppingListTable.CREATE_STATEMENT);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "DatabaseHelper onUpgrade");
db.execSQL("DROP TABLE IF EXISTS " + ShoppingListItemTable.TABLE_NAME);
db.execSQL("DROP TABLE IF EXISTS " + ShoppingListTable.TABLE_NAME);
onCreate(db); //this will recreate the database as if it were new
}
}
public SQLiteDatabase open(){
mDbHealper = new DatabaseHelper(mCtx);
mDb = mDbHealper.getReadableDatabase();
return mDb;
}
public void close(){
mDb = null;
}
}
I have tried to declare variables within onCreate so I can use with other methods in the class like this
//================DATABASE CONNECTION=====================//
private ShoppingListDatabase databaseConnection;
private SQLiteDatabase db = databaseConnection.open();
private String selectedList;
private int selectedID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
setContentView(R.layout.activity_main_lists_detail);
ShoppingListDatabase databaseConnection = new ShoppingListDatabase(this);
SQLiteDatabase db = databaseConnection.open();
lists = ShoppingListItemTable.selectAllItems(db, selectedID);
and this is the error
Process: com.puyakul.prin.psychic_shopping, PID: 5635
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.puyakul.prin.psychic_shopping/com.puyakul.prin.psychic_shopping.MainListsDetail}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase com.puyakul.prin.psychic_shopping.ShoppingListDatabase.open()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase com.puyakul.prin.psychic_shopping.ShoppingListDatabase.open()' on a null object reference
at com.puyakul.prin.psychic_shopping.MainListsDetail.<init>(MainListsDetail.java:46)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1078)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538)
Opening and closing the connection can be inefficient/costly so perhaps introduce/use the following :-
public SQLiteDatabase open(){
if (mDb == null) {
mDbHealper = new DatabaseHelper(mCtx);
mDb = mDbHealper.getReadableDatabase();
}
return mDb;
}
or alternately :-
public synchronized SQLiteDatabase open(){
if (mDb == null) {
mDbHealper = new DatabaseHelper(mCtx);
mDb = mDbHealper.getReadableDatabase();
}
return mDb;
}
and never call the close, except when the main activity is being destroyed. Then you will retrieve the one connection.
Here's some example uses based upon your ShoppingListDatabase class.
First a modified class with a few extra methods inside (addShoppingList, getAllShoppingListsAsCursor and logDBTables) and just a very simple shoppinglist table :-
public class ShoppingListDatabase {
private static final String TAG = "ShoppingListDatabase";
private static final String DATABASE_NAME = "ShoppingListDatabase";
private static final int DATABASE_VERSION = 3;
private static final String TBNAME = "shoppinglist";
public static final String COL_SHOPPINGLIST_NAME = "shoppinglist_name";
private SQLiteDatabase mDb;
private DatabaseHelper mDbHealper;
private final Context mCtx;
public ShoppingListDatabase(Context ctx){
this.mCtx = ctx;
}
/**
* DatabaseHelper class.
*
* Database helper class to manage connections with the database.
*/
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
Log.d(TAG, "DatabaseHelper onCreate");
//db.execSQL(ShoppingListItemTable.CREATE_STATEMENT);
//db.execSQL(ShoppingListTable.CREATE_STATEMENT);
String crtsql = "CREATE TABLE If NOT EXISTS " + TBNAME + "(" +
COL_SHOPPINGLIST_NAME + " TEXT " +
")";
db.execSQL(crtsql);
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d(TAG, "DatabaseHelper onUpgrade");
//db.execSQL("DROP TABLE IF EXISTS " + ShoppingListItemTable.TABLE_NAME);
//db.execSQL("DROP TABLE IF EXISTS " + ShoppingListTable.TABLE_NAME);
onCreate(db); //this will recreate the database as if it were new
}
}
public synchronized SQLiteDatabase open(){
if (mDb == null) {
mDbHealper = new DatabaseHelper(mCtx);
mDb = mDbHealper.getReadableDatabase();
}
return mDb;
}
public void close(){
mDb = null;
}
public long addShoppingList(String name) {
ContentValues cv = new ContentValues();
cv.put(COL_SHOPPINGLIST_NAME,name);
return mDb.insert(TBNAME,null,cv);
}
public Cursor getAllShoppingListAsCursor() {
return mDb.query(TBNAME,
null,
null,
null,
null,null,
null
);
}
public void logDBTables() {
Cursor csr = mDb.query("sqlite_master",null,null,null,null,null,null);
while (csr.moveToNext()) {
Log.d(TAG,"Item " +
csr.getString(csr.getColumnIndex("name")) +
" was created using " +
csr.getString(csr.getColumnIndex("sql"))
);
}
}
}
Here's code from an Activity (that uses the Database connection in various ways) :-
public class MainActivity extends AppCompatActivity {
ShoppingListDatabase mSL;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSL = new ShoppingListDatabase(this);
mSL.open();
SO50312618();
SO50312618_other();
Cursor csr = mSL.getAllShoppingListAsCursor();
while(csr.moveToNext()) {
Log.d("SL INFO","Shopping List " + String.valueOf(csr.getPosition() + 1) +
" is " +
csr.getString(csr.getColumnIndex(ShoppingListDatabase.COL_SHOPPINGLIST_NAME))
);
}
}
private void SO50312618() {
ShoppingListDatabase databaseConnection = new ShoppingListDatabase(this);
SQLiteDatabase db = databaseConnection.open();
databaseConnection.logDBTables();
}
private void SO50312618_other() {
mSL.addShoppingList("List001");
mSL.addShoppingList("List002");
}
}
The results being :-
05-13 05:36:24.290 4245-4245/soanswers.soanswers D/ShoppingListDatabase: Item android_metadata was created using CREATE TABLE android_metadata (locale TEXT)
Item shoppinglist was created using CREATE TABLE shoppinglist(shoppinglist_name TEXT )
05-13 05:36:24.302 4245-4245/soanswers.soanswers D/SLĀ INFO: Shopping List 1 is List001
Shopping List 2 is List002
All the various uses will use the same single connection.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I'm trying to populate my database to listview through simple cursor adapter via intent to new activity. Cant figure out why is it crashing?
This is my Database helper class:
public class DBhelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "Mydatabase.db";
public static final String TABLE_NAME = "contacts";
public static final String _ID = "_ID";
public static final String COL_2 = "NAME";
public static final String COL_3 = "PHONE";
public static final String COL_4 = "EMAIL";
public static final String COL_5 = "HQ";
public static final String COL_6 = "ADDRESS";
public DBhelper(Context context) {
super(context, DATABASE_NAME, null, 1);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table contacts"+ "(_id integer primary key autoincrement, name text, phone text, email text, hq text, address text)");
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS contacts");
onCreate(db);
}
public boolean insertContact (String name, String phone, String email, String hq, String address){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(COL_2,name);
contentValues.put(COL_3,phone);
contentValues.put(COL_4,email);
contentValues.put(COL_5,hq);
contentValues.put(COL_6,address);
db.insert(TABLE_NAME,null,contentValues);
return true;
}
public Cursor getAllDAta(){
Cursor cursor;
String[] columns = {DBhelper._ID, DBhelper.COL_2, DBhelper.COL_3, DBhelper.COL_4, DBhelper.COL_5, DBhelper.COL_6};
SQLiteDatabase db = this.getWritableDatabase();
cursor = db.query(DBhelper.TABLE_NAME,columns, null, null, null, null, null);
return cursor;
}
DBhelper dbHelper;
SQLiteDatabase database;
Context context;
public DBhelper open() throws SQLException {
dbHelper = new DBhelper(context);
database = dbHelper.getWritableDatabase();
return this;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
DBhelper mydb;
EditText name, phone, email, hq, address;
Button addData, viewData;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mydb = new DBhelper(this);
name = (EditText) findViewById(R.id.editName);
phone = (EditText) findViewById(R.id.editPhone);
email = (EditText) findViewById(R.id.editEmail);
hq = (EditText) findViewById(R.id.editHQ);
address = (EditText) findViewById(R.id.editAddress);
addData = (Button) findViewById(R.id.addData);
viewData = (Button) findViewById(R.id.viewData);
}
public void addClick(View view){
String nm, ph, em, h, as;
nm = name.getText().toString();
ph = phone.getText().toString();
em = email.getText().toString();
h = hq.getText().toString();
as = address.getText().toString();
boolean checkk = mydb.insertContact(nm,ph,em,h,as);
if (checkk = true) {
Toast.makeText(MainActivity.this, "Data Added", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(MainActivity.this,"Data Not Added",Toast.LENGTH_LONG).show();
}
}
public void showClick(View v1){
Intent intent = new Intent(MainActivity.this,Displayc.class);
startActivity(intent);
finish();
}
}
My display activity
public class Displayc extends AppCompatActivity {
ListView listView;
DBhelper mydb1;
SimpleCursorAdapter adapter;
final String[] from = new String[] {DBhelper._ID, DBhelper.COL_2, DBhelper.COL_3, DBhelper.COL_4, DBhelper.COL_5, DBhelper.COL_6};
final int[] to = new int[] {R.id.idv, R.id.namev, R.id.phonev, R.id.emailv, R.id.hqv, R.id.addressv };
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_displayc);
listView = (ListView) findViewById(R.id.list_sq);
mydb1 = new DBhelper(this.getBaseContext());
mydb1.open();
Cursor c = mydb1.getAllDAta();
adapter = new SimpleCursorAdapter(getBaseContext(),R.layout.template,c,from,to,0);
listView.setAdapter(adapter);
}
}
Error message:
[java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bibulkumar.sqliteapp/com.example.bibulkumar.sqliteapp.Displayc}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
[Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.sqlite.SQLiteDatabase android.content.Context.openOrCreateDatabase(java.lang.String, int, android.database.sqlite.SQLiteDatabase$CursorFactory, android.database.DatabaseErrorHandler)' on a null object reference
Context context;
public DBhelper open() throws SQLException {
dbHelper = new DBhelper(context);
database = dbHelper.getWritableDatabase();
return this;
The context you use here is not initialized and therefore null. Hence the NPE when you're calling getWritableDatabase().
Remove the open() and any calls to it - you don't actually need it for anything.
I am a little confused how to do this properly. Here is my DatabaseHelper class:
public class DatabaseHelper extends SQLiteOpenHelper {
private static DatabaseHelper mInstance = null;
private static final String DB_NAME = "database.db";
private static final int DB_VERSION = 1;
private Context mContext;
public static DatabaseHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new DatabaseHelper(context.getApplicationContext());
}
return mInstance;
}
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}
...
Assuming this is right, is this the correct way to handle the querying class:
public class DatabaseProcessor {
private SQLiteDatabase mDatabase;
private DatabaseHelper mSQLHelper;
private Context mContext;
public DatabaseProcessor(Context context) {
mContext = context;
mSQLHelper = new DatabaseHelper(mContext);
}
private void open() throws SQLException {
mDatabase = mSQLHelper.getWritableDatabase();
}
private void close() {
mDatabase.close();
}
public void insertSomethingIntoDb(String key) {
ContentValues values = new ContentValues();
values.put("some_column_name", name);
open();
mDatabase.insert("some_table_name", null, values);
close();
}
...
And if this is right, how do I properly invoke a db method from somewhere else in the code such as an Activity, Fragment, etc, anywhere.
You should make the DatabaseHelper constructor private and create instances of this class by using the getInstance method. eg: mSQLHelper = DatamabseHelper.getInstance(context).
To call a method of this class, you can do something like this.
DatabaseHelper.getInstance(context).someFunction(...);
And to use any of the DatabaseProcessor functions, you can do this:
new DatabaseProcessor(context).insertSomethingIntoDb(...);
Keep in mind that this singleton approach has some problems, for starters, it doesn't support multithreading, there is no mechanism in place to assure that if two threads ask for an instance at the same time, only one instance will be created.
public class DBHelper extends SQLiteOpenHelper {
private static final int DB_VERSION=1;
private static final String DB_NAME="SAMPLE.db";
private static final String TABLE_NAME="events";
private static final String KEY_ID="sampleId";
private static final String KEY_TITLE="sampleTitle";
private static final String KEY_DATE="sampleDATE";
SQLiteDatabase dbEvents;
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS sampleTable(sampleID INTEGER PRIMARY KEY AUTOINCREMENT,sampleTitle TEXT,sampleDATE BIGINT,trash INTEGER DEFAULT 0) ");
this.dbEvents=db;
}
public Integer deleteItem(Integer itemId){
Log.d("CURSOR:","IM HERE"+eventId);
if(dbEvents == null){
Log.d("CURSOR:","IM NOT INTIALIZING");
}
return null;
}
Where I'm getting IM NOT INTIALIZING
and in my Activity I'm calling as [When Delete Button is clicked]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper=new DBHelper(this);
}
public void deleteItem(int Id){
dbHelper=new DBHelper(this);
dbHelper.deleteEvent(Id);
}
I cannot perform DB operation where it throws to Null Pointer Exception.
thanks in advance
onCreate will be called, when you call getWritableDataBase() method with an instance of your DBHelper.
From the Javadocs for the method getWritableDataBase() with an instance of a class that extends SQLiteOpenHelper
Create and/or open a database that will be used for reading and writing. The first time this is called, the database will be opened and onCreate, onUpgrade and/or onOpen will be called.
This means, that this code
#Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE IF NOT EXISTS sampleTable(sampleID INTEGER PRIMARY KEY AUTOINCREMENT,sampleTitle TEXT,sampleDATE BIGINT,trash INTEGER DEFAULT 0) ");
this.dbEvents=db;
}
won't get you far. Since creating by calling getWritableDataBase or getReadableDataBase returns a SQLiteDatabase instance for performing SQLite operations.
So, from an Activity if you want to access your Database you have to do the following:
DBHelper dbHelper = new DBHelper(this);
SQLiteDatabase db = dbHelper.getWritableDataBase();
db.query("SELECT * FROM " + sampleTable);