Do you have any threading going on of your own creation? Some code that might be resetting mSQLDBreader
via another method. Perhaps that thread occasionally runs and trashes the value of mSQLDBreader before you use it?
Have you ever witnessed this on an emulator running 2.3.x?
I looked at google's code for getReadableDatabase, and I don't see a way that it could return null. Gory details are below if you are interested. Based on what I see, I would suspect either a multithreading bug in your code, or a bug introduced by customizations to the android code by the manufacturer of the devices you tested (if that is even plausible.)
Gory details All paths through getReadableDatabase invoke methods on the return object after creating it. So the value can't be null at that point. Otherwise the NPE would be raised from inside.
Here is a snippet of the 2.3.6 code for getReadableDatabase. Actual source is available on grepcode.
public synchronized SQLiteDatabase getReadableDatabase() {
if (mDatabase != null && mDatabase.isOpen()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) { /* snip throw ISE */ }
try {
return getWritableDatabase();
} catch (SQLiteException e) {
// snip : throws or falls through below
}
SQLiteDatabase db = null;
try {
mIsInitializing = true;
String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
// *** next line calls method on db. NPE would be here if db was null at this point. ***
if (db.getVersion() != mNewVersion) {
// snip throw.
}
onOpen(db);
Log.w(TAG, "Opened " + mName + " in read-only mode");
mDatabase = db;
return mDatabase;
} finally {
// snip : not relevant
}
}
Notice that getReadableDatabase usually just returns the result of getWritableDatabase. He looks like this:
public synchronized SQLiteDatabase getWritableDatabase() {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) {
throw new IllegalStateException("getWritableDatabase called recursively");
}
// snip comment about locking
boolean success = false;
SQLiteDatabase db = null;
if (mDatabase != null) mDatabase.lock();
try {
mIsInitializing = true;
if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
db = mContext.openOrCreateDatabase(mName, 0, mFactory);
}
int version = db.getVersion(); // ** method called on result!
// snip block that has more method calls and never nulls out db
onOpen(db);
success = true;
return db;
} finally {
// snip
mDatabase = db;
// snip rest of finally block that isn't relevant.
}
}
Lastly, it is important to note that both of these methods, as well as the close method of SqliteOpenHelper, are tagged with synchronize, so there is no way for one method to trash the state of the other if you have multiple threads calling these methods at the same time..