Я реализовал логику для обновления моей базы данных до новых версий. И все работает нормально, иначе я бы получил тысячи аварий.
В любом случае во время onUpgrade происходит около 100 сбоев в месяц, и все они из BroadcastReceiver BOOT_COMPLETED
.
Вот журнал сбоев:
android.database.sqlite.SQLiteException:
at android.database.sqlite.SQLiteConnection.nativePrepareStatement (SQLiteConnection.java)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement (SQLiteConnection.java:903)
at android.database.sqlite.SQLiteConnection.prepare (SQLiteConnection.java:514)
at android.database.sqlite.SQLiteSession.prepare (SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init> (SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init> (SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql (SQLiteDatabase.java:1770)
at android.database.sqlite.SQLiteDatabase.execSQL (SQLiteDatabase.java:1698)
at com.abdula.pranabreath.common.helpers.DbUpgradeHelper.upgradeToTrngSounds (DbUpgradeHelper.java:213)
at com.abdula.pranabreath.common.helpers.DbOpenHelper.onUpgrade (DbOpenHelper.java:101)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked (SQLiteOpenHelper.java:398)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:298)
at com.abdula.pranabreath.common.helpers.DbOpenHelper.getAllMeta (DbOpenHelper.java:224)
at com.abdula.pranabreath.model.proxies.ControlProxy.queryMetadata (ControlProxy.java:101)
at com.abdula.pranabreath.presenter.Presenter.bindData (Presenter.java:179)
at com.abdula.pranabreath.presenter.receivers.ReminderBootCompletedReceiver$1.run (ReminderBootCompletedReceiver.java:27)
Таким образом, BOOT_COMPLETED
получатель загружает все напоминания из базы данных и планирует следующее время срабатывания тревоги.
Вот класс получателя:
public void onReceive(final Context context, Intent intent) {
final String action = intent.getAction();
final PendingResult result = goAsync();
final Thread thread = new Thread() {
public void run() {
switch (action) {
case Intent.ACTION_BOOT_COMPLETED:
sPresenter.bindData();
ReminderDelegate.setNextReminder();
break;
}
result.finish();
}
};
thread.start();
}
}
sPresenter.bindData (); call загружает все данные из базы данных, используя метод getAllMeta, а затем вызывает getWritableDatabase () изнутри. После вызывается onUpgrade.
В этом случае кажется, что пользователь обновил приложение и не открыл его, а перезагрузил устройство.
Метод onUpgrade:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
int version = oldVersion;
db.beginTransaction();
switch (version) {
case LAUNCH_VERSION:
DbUpgradeHelper.upgradeToAccurateExp(db);
version = ACCURATE_EXP_VERSION;
case ACCURATE_EXP_VERSION:
DbUpgradeHelper.upgradeToGuruRelease(db);
version = GURU_RELEASE_VERSION;
case GURU_RELEASE_VERSION:
DbUpgradeHelper.upgradeToMeditation(db);
version = MEDITATION_VERSION;
case MEDITATION_VERSION:
DbUpgradeHelper.upgradeToTrngSounds(db);
version = TRNG_SOUNDS_VERSION;
}
db.setTransactionSuccessful();
db.endTransaction();
}
И последний метод, где происходит сбой:
static void upgradeToTrngSounds(final SQLiteDatabase db) {
db.execSQL("ALTER TABLE trainings ADD COLUMN public_id INTEGER"); // CRASH HERE
db.execSQL("UPDATE trainings SET public_id = user_owner");
db.execSQL("ALTER TABLE trainings ADD COLUMN dur_mode INTEGER DEFAULT 0");
}
Других жалоб нет - только исключение SQLiteException.
Не могли бы вы помочь мне выяснить, есть ли проблема с тем, что onUpgrade не работает в UI-потоке? Или что-то не так с BroadcastReceiver?