Search code examples
androidandroid-sqlitesqliteopenhelper

SQLiteReadOnlyDatabaseException on database update on writeable database


Whenever I update my database I get this error. But when I rerun the app as it is, the database gets updated.

android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database (code 1032)[

Code:

 public DBAdapter(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
    ctx = context;
    db = getWritableDatabase();
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (oldVersion != newVersion) {
        ctx.deleteDatabase(DATABASE_NAME);
        new DBAdapter(ctx);
    } else {
        super.onUpgrade(db, oldVersion, newVersion);
    }
}

As one of the SO answers suggested, I have added this too:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

BTW: I am using SQLiteAssetHelper to create prebuilt database


Solution

  • This is not a solution to prevent this issue but a work around.

     public DBAdapter(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        ctx = context;
        try {
            db = getWritableDatabase();
        } catch (SQLiteReadOnlyDatabaseException e){
            ctx.startActivity(new Intent(ctx, MainActivity.class));
        }
    }
    
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (oldVersion != newVersion) {
            ctx.deleteDatabase(DATABASE_NAME);
            new DBAdapter(ctx);
        } else {
            super.onUpgrade(db, oldVersion, newVersion);
        }
    }
    

    First time when the adapter is initialized, a writable db is created. Then onUpgrade gets called. Here when the database is deleted, the adapter get reinitialized. But the connection of the db is not deleted and persists hence, the second time when db = getWritableDatabase(); is executed SQLiteReadOnlyDatabaseException occurs. The original activity that initialized DBAdapter is restarted. Now the Adapter is reinitialized and the onUpgrade method is not called and hence SQLiteReadOnlyDatabaseException does not occur.

    All this process happens very fast and the user experience does not become bad in my case.

    Note: new DBAdapter(ctx); does not seem to be necessary and deleteDatabase seems to recreate the adapter. But for caution, I have written this line of code.

    I would love to get some information on the cause and solution for this error.