In my content provider I create and maintain 3 SQLiteDatabase
objects. They are created like this:
private ContentProviderHelper helper;
@Override
public boolean onCreate() { // that's the ContentProvider onCreate()
SQLiteDatabase dbLog = new DbLog(getContext()).getWritableDatabase();
SQLiteDatabase dbSession = new DbSession(getContext()).getWritableDatabase();
SQLiteDatabase dbLocation = new DbLocation(getContext()).getWritableDatabase();
helper = new ContentProviderHelper(UriManager.getAuthority(getContext()));
helper.addDb(dbLog, DbLog.TABLE_NAME, UriManager.LOG, SQLiteDatabase.CONFLICT_REPLACE);
helper.addDb(dbSession, DbSession.TABLE_NAME, UriManager.SESSION, SQLiteDatabase.CONFLICT_REPLACE);
helper.addDb(dbLocation, DbLocation.TABLE_NAME, UriManager.LOCATION, SQLiteDatabase.CONFLICT_REPLACE);
the ContentProviderHelper stores those SQLiteDatabase
in an ArrayList
indexed with the UriMatcher
.
The <provider>
is properly registered in the manifest and my app have SD-card permission.
It runs fine for most of our 500.000 user base, but every once in a while I get a SQLiteCantOpenDatabaseException: unable to open database file
from the Google Play
the relevant stack track is:
Caused by: android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file
at android.database.sqlite.SQLiteDatabase.dbopen(Native Method)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:1013)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:986)
at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatabase.java:1051)
at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:787)
at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:221)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:157)
most often than not those error reports come from generic brandless poor quality devices.
Any help on how to properly avoid those errors will be much appreciated.
edit:
a different SQL exceptions that I'm getting on the same code.
Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error: COMMIT;
at android.database.sqlite.SQLiteDatabase.native_execSQL(Native Method)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1763)
at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:583)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:137)
at ***.***.***.data.ContentManager.onCreate(ContentManager.java:26)
so is there any other way of handling this besides try{} catch(){}
the hell out of it ?
edit:
Extra info regarding cursors usage:
In general cursors are kept opened for the minimum amount of time as possible. All 3 SQLiteDatabase have a Wrapper that do the actual Cursor calls, read the data from them and close them. There's only 1 instance where the cursor is passed back to the calling object, but it is an IntentService
, again, single thread, single instance, single process (just like ContentProvider) that loops through the cursor and close it.