Android App Crashes on Startup: SQLite NullPointerException in ContactsFragment
It looks like you accidentally created a context
local variable instead of using the instance variable.
So, context
is null when you pass it into MyDBHandler
, so when you call this.getWritableDatabase()
, this
is null. As a result, you get the NullPointerException
, as you can see in the log:
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 at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:224) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
Try moving all of the Context
related code to onActivityCreated()
to ensure you have a valid Context
, and make sure to use the instance variable instead of a local variable:
public class ContactsFragment extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor> {private CursorAdapter mAdapter;private Context context; //this is the Context you will useTextView idView;@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // create adapter once //Context context = getActivity(); //Here was the problem //int layout = R.layout.activity_list_item_1; //Cursor c = null; // there is no cursor yet //int flags = 0; // no auto-requery! Loader requeries. //mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags);}public void ContactsDb(Context context) { this.context=context;}Uri contentUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;String[] PROJECTION = { ContactsContract.Contacts.HAS_PHONE_NUMBER, ContactsContract.Contacts._ID, // _ID is always required ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME_PRIMARY, // that is what we want to display Contacts.TIMES_CONTACTED, ContactsContract.CommonDataKinds.Phone.NUMBER};@Overridepublic void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //Add this here: context = getActivity(); //use the instance variable int layout = R.layout.activity_list_item_1; Cursor c = null; // there is no cursor yet int flags = 0; // no auto-requery! Loader requeries. mAdapter = new SimpleCursorAdapter(context, layout, c, FROM, TO, flags); // each time we are started use our listadapter setListAdapter(mAdapter); // and tell loader manager to start loading getLoaderManager().initLoader(0, null, this);}// columns requested from the database// and name should be displayed in the text1 textview in item layoutpublic String[] has_phone = {ContactsContract.Contacts.HAS_PHONE_NUMBER}; String phone = "0"; int dbPhone = 0;private final String[] FROM = {Contacts.DISPLAY_NAME_PRIMARY, ContactsContract.CommonDataKinds.Phone.NUMBER};private final int[] TO = {android.R.id.text1, dbPhone};public void newContact (View view) { //context should now be valid: MyDBHandler dbHandler = new MyDBHandler(context, null, null, 1); String name = Contacts.DISPLAY_NAME_PRIMARY; int dbPhone = Integer.parseInt(phone); String status =""; String blurb =""; ContactsDb contacts = new ContactsDb(name, dbPhone, status, blurb); dbHandler.addContact(contacts);}//........
make object from db class in onCreateViewHolder method in adapter to solve this error