I use a SQLite database in my Android app which I access using a DBHelper and a custom ContentProvider. I now want to import a database by replacing the current one with one I previously exported from the app by simply copying it to another location.
However, after replacing the database, the in-memory copy of the old database continues to be used until I close and restart the app.
-> How can I force a reload of the database?
Additional Info
It works well, when I export the .db file along with the .db-shm and .db-wal files and import all 3 files instead of just the .db file.
However, if I open the .db file with sqlite3 on my laptop, close it (such that the .db file contains all the necessary information and .db-shm and .db-wal are automatically deleted) and try to import just this .db file, the behavior is as described above.
My Code
The DBHelper class:
public class MyDbHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "mydb.db";
private static final int DATABASE_VERSION = 2;
private static MyDbHelper mInstance = null;
MyDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE table1 ...;");
db.execSQL("CREATE TABLE table2 ...;");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("CREATE TABLE IF NOT EXISTS table3 ...;");
}
static MyDbHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MyDbHelper(context.getApplicationContext());
}
return mInstance;
}}
In the ContentProvider onCreate() method, I instantiate the DBHelper like this:
mDbHelper = MyDbHelper.getInstance(getContext());
and then get the writable/readable database instance inside of each method in the ContentProvider as suggested here.
What I tried already
I tried implementing a reopen method in the DBHelper
public static void reopen(Context context) {
mDBHelper = new MyDBHelper(context);
}
as suggested here and calling it after the import, but still the new database is only used once the app was closed and restarted.
I also tried a reset method
public void reset(Context context) {
mDBHelper.close();
mDBHelper = new MyDBHelper(context);
}
as described here but this results in the app crashing with
2019-08-03 14:58:13.091 21814-21887/? E/SQLiteLog: (522) statement aborts at 3: [SELECT _id, title, cover_path FROM albums ORDER BY CAST(title as SIGNED) ASC, LOWER(title) ASC] disk I/O error
2019-08-03 14:58:13.092 21814-21887/? E/SQLiteQuery: exception: disk I/O error (code 522 SQLITE_IOERR_SHORT_READ); query: SELECT _id, title, cover_path FROM albums ORDER BY CAST(title as SIGNED) ASC, LOWER(title) ASC
2019-08-03 14:58:13.115 21814-21887/? E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #4
Process: com.mycompany.myapp, PID: 21814
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:354)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by: android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 522 SQLITE_IOERR_SHORT_READ)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:859)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:149)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:137)
at android.content.ContentResolver.query(ContentResolver.java:821)
at android.content.ContentResolver.query(ContentResolver.java:752)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:68)
at android.content.CursorLoader.loadInBackground(CursorLoader.java:45)
at android.content.AsyncTaskLoader.onLoadInBackground(AsyncTaskLoader.java:319)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:73)
at android.content.AsyncTaskLoader$LoadTask.doInBackground(AsyncTaskLoader.java:61)
at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)