SQLiteOpenHelper.getWriteableDatabase() null pointer exception on Android
I've had fine luck using SQLite with straight, direct SQL in Android, but this is the first time I'm wrapping a DB in a ContentProvider. I keep getting a null pointer exception when calling getWritableDatabase()
or getReadableDatabase()
. Is this just a stupid mistake I've made with initializations in my code or is there a bigger issue?
public class DatabaseProvider extends ContentProvider {
...
private DatabaseHelper databaseHelper;
private SQLiteDatabase db;
...
@Override
public boolean onCreate() {
databaseHelper = new DatabaseProvider.DatabaseHelper(getContext());
return (databaseHelper == null) ? false : true;
}
...
@Override
public Uri insert(Uri uri, ContentValues values) {
db = databaseHelper.getWritableDatabase(); // NULL POINTER EXCEPTION HERE
...
}
private static class DatabaseHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "cogsurv.db";
public static final int DATABASE_VERSION = 1;
public static final String[] TABLES = {
"people",
"travel_logs",
"travel_fixes",
"landmarks",
"landmark_visits",
"direction_distance_estimates"
};
// people._id does not AUTOINCREMENT, because it's set based on server's people.id
public static final String[] CREATE_TABLE_SQL = {
"CREATE TABLE people (_id INTEGER PRIMARY KEY," +
"server_id INTEGER," +
"name VARCHAR(255)," +
"email_address VARCHAR(255))",
"CREATE TABLE travel_logs (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"server_id INTEGER," +
"person_local_id INTEGER," +
"person_server_id INTEGER," +
"start DATE," +
"stop DATE," +
"type VARCHAR(15)," +
"uploaded VARCHAR(1))",
"CREATE TABLE travel_fixes (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"datetime DATE, " +
"latitude DOUBLE, " +
"longitude DOUBLE, " +
"altitude DOUBLE," +
"speed DOUBLE," +
"accuracy DOUBLE," +
"travel_mode VARCHAR(50), " +
"person_local_id INTEGER," +
"person_server_id INTEGER," +
"travel_log_local_id INTEGER," +
"travel_log_server_id INTEGER," +
"uploaded VARCHAR(1))",
"CREATE TABLE landmarks (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"server_id INTEGER," +
"name VARCHAR(150)," +
"latitude DOUBLE," +
"longitude DOUBLE," +
"person_local_id INTEGER," +
"person_server_id INTEGER," +
"uploaded VARCHAR(1))",
"CREATE TABLE landmark_visits (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"server_id INTEGER," +
"person_local_id INTEGER," +
"person_server_id INTEGER," +
"landmark_local_id INTEGER," +
"landmark_server_id INTEGER," +
"travel_log_local_id INTEGER," +
"travel_log_server_id INTEGER," +
"datetime DATE," +
"number_of_questions_asked INTEGER," +
"uploaded VARCHAR(1))",
"CREATE TABLE direction_distance_estimates (_id INTEGER PRIMARY KEY AUTOINCREMENT," +
"server_id INTEGER," +
"person_local_id INTEGER," +
"person_server_id INTEGER," +
"travel_log_local_id INTEGER," +
"travel_log_server_id INTEGER," +
"landmark_visit_local_id INTEGER," +
"landmark_visit_server_id INTEGER," +
"start_landmark_local_id INTEGER," +
"start_landmark_server_id INTEGER," +
"target_landmark_local_id INTEGER," +
"target_landmark_server_id INTEGER," +
"datetime DATE," +
"direction_estimate DOUBLE," +
"distance_estimate DOUBLE," +
"uploaded VARCHAR(1))"
};
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
Log.v(Constants.TAG, "DatabaseHelper()");
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.v(Constants.TAG, "DatabaseHelper.onCreate() starting");
// create the tables
int length = CREATE_TABLE_SQL.length;
for (int i = 0; i < length; i++) {
db.execSQL(CREATE_TABLE_SQL[i]);
}
Log.v(Constants.TAG, "DatabaseHelper.onCreate() finished");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
for (String tableName : TABLES) {
db.execSQL("DROP TABLE IF EXISTS" + tableName);
}
onCreate(db);
}
}
}
As always, thanks for the assistance!
--
Not sure if this detail helps, but here's LogCat showing the exception:
开发者_开发百科removed dead ImageShack link
Rather than:
databaseHelper = new DatabaseProvider.DatabaseHelper(getContext());
try:
databaseHelper = new DatabaseProvider.DatabaseHelper(this);
and see if that helps.
If it does not, could you post the NullPointerException
stack trace?
This error is almost certainly from having an invalid context passed into:
super(context, DATABASE_NAME, null, DATABASE_VERSION);
I just had this problem with the SQLite nullpointerexception in a non-activity and the problem was that it had an invalid context.
My fix was passing the context at onCreate instead of the constructor. Try finding a context from another place to do getApplicationContext()
.
try use getWritableDatabase()
in some time after you initial the helper
you got NullPointerException
cause the database was not prepared completely
and don't do that in the ui thread, or it may cause ANR
I just had this problem and realised it was a bit of a red herring.
My issue stemmed from the way I was using the ContentProvider.
I was actually accessing the ContentProvider directly rather than through the ContentResolver. It's essentially an easy way to trip up if your new to using ContentProviders.
Hope that helps :)
Make sure when you're creating the AVD, specify some amount of SD card space. I had the same problem and this solved it. If this doesn't help, you can also try to start the emulator with -wipe-data option.
I got this same NullPointerException error when getReadableDatabase() is getting called inside query() because I was improperly querying my content provider. I can't see anything wrong with the way you are constructing your database. getContext() should give you the appropriate context object. However, I would pay attention to how you are making your queries to the content provider. You should make sure that you have a valid reference to your content resolver (ie. by calling getContentResolver().query(..)) and is using that to perform the query.
精彩评论