* Append new migrations to the end of the list to keep it sorted ascending. * If not sorted correctly, migrations which depend on each other, may fail. */ private static final Migration[] SETTING_MIGRATIONS = { MIGRATION_0_1, MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, }; /** * Version number for preferences. Must be incremented every time a migration is necessary. */ public static final int VERSION = 5; public static void initMigrations(final Context context, final boolean isFirstRun) { // setup migrations and check if there is something to do sp = PreferenceManager.getDefaultSharedPreferences(context); final String lastPrefVersionKey = context.getString(R.string.last_used_preferences_version); final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0); // no migration to run, already up to date if (isFirstRun) { sp.edit().putInt(lastPrefVersionKey, VERSION).apply(); return; } else if (lastPrefVersion == VERSION) { return; } // run migrations int currentVersion = lastPrefVersion; for (final Migration currentMigration : SETTING_MIGRATIONS) { try { if (currentMigration.shouldMigrate(currentVersion)) { if (DEBUG) { Log.d(TAG, "Migrating preferences from version " + currentVersion + " to " + currentMigration.newVersion); } currentMigration.migrate(context); currentVersion = currentMigration.newVersion; } } catch (final Exception e) { // save the version with the last successful migration and report the error sp.edit().putInt(lastPrefVersionKey, currentVersion).apply(); ErrorUtil.openActivity(context, new ErrorInfo( e, UserAction.PREFERENCES_MIGRATION, "Migrating preferences from version " + lastPrefVersion + " to " + VERSION + ". " + "Error at " + currentVersion + " => " + ++currentVersion )); return; } } // store the current preferences version sp.edit().putInt(lastPrefVersionKey, currentVersion).apply(); } private SettingMigrations() { } abstract static class Migration { public final int oldVersion; public final int newVersion; protected Migration(final int oldVersion, final int newVersion) { this.oldVersion = oldVersion; this.newVersion = newVersion; } /** * @param currentVersion current settings version * @return Returns whether this migration should be run. * A migration is necessary if the old version of this migration is lower than or equal to * the current settings version. */ private boolean shouldMigrate(final int currentVersion) { return oldVersion >= currentVersion; } protected abstract void migrate(Context context); } }