Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't downgrade database from version `n` to `n-1` on Samsung

I have an application with a database, created and opened using the standard SQLiteOpenHelper.

Whenever I upgrade the database version, I also upgrade the application's version code, so there is no way for the database to go down (the database version number is always increased, never decreased).

I disabled database backup in my app by setting the android:allowBackup property to false.

But when I upgrade the app on the Play Store, I get a lot of crash

Can't downgrade database from version n to n-1

96% of those crash occur on Samsung device running . Anyone know why this problem occurs, and more importantly how to prevent this crash ?

I know that I can override the onDowngrade to prevent the crash but I actually don't understand why the onDowngrade is called at all as the crash is called on an app that always use the last version of the database.

Edit : Added code sample, FWIW

My OpenHelper :

public class MyDBHelper extends SQLiteOpenHelper {

    private static final String LOG_TAG = MyDBHelper.class.getName();

    public static final String DB_NAME = "my_db";
    public static final int DB_V1 = 1;
    public static final int DB_V2_UNIQUE_IDS = 2;
    public static final int DB_V3_METADATAS = 3;
    public static final int DB_V4_CORRUPTED_IDS = 4;
    public static final int DB_V5_USAGE_TABLE = 5;

    public static final int DB_VERSION = DB_V5_USAGE_TABLE;

    public MyDBHelper(final Context context, IExceptionLogger logger) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(final SQLiteDatabase db) {
        Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onCreate()");
        db.execSQL(createMyTable());
    }

    @Override
    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
        Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): oldVersion = " + oldVersion + " : newVersion = " + newVersion);

        if (oldVersion < 2) {
            Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): upgrading version 1 table to version 2");
            db.execSQL(upgradeTable_v1_to_v2());
        }

        if (oldVersion < 3) {
            Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onUpgrade(): upgrading version 2 Entry table to version 3");
            db.execSQL(upgradeTable_v2_to_v3());
        }
    }

    @Override
    @TargetApi(Build.VERSION_CODES.FROYO)
    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
        Debug.log_d(DebugConfig.DEFAULT, LOG_TAG, "onDowngrade(): oldVersion = " + oldVersion + " : newVersion = " + newVersion);
        super.onDowngrade(db, oldVersion, newVersion);
    }
}

And how I initialize it :

public class DatabaseController {

    private MyDBHelper mDBHelper;

    public void initialize(final Context context) {

       mDBHelper = new MyDBHelper(context);

    }
}
like image 552
XGouchet Avatar asked Apr 04 '17 07:04

XGouchet


1 Answers

This is the default implementation of SQLiteOpenHelper.onDowngrade(...):

public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    throw new SQLiteException("Can't downgrade database from version " +
            oldVersion + " to " + newVersion);
}

As you see if you call super.onDowngrade(...), as you do, you'll get that exception. You need to implement onDowngrade yourself, without calling super.onDowngrade. It should always be implemented for the sake of completeness, as there's no guarantee when it might be called - it sounds strange that the user has changed to use an older version of the app but there might be a situation like that. Do you know what version of the app the exceptions come from?

like image 104
etan Avatar answered Nov 02 '22 03:11

etan