来自BroadcastReceiver的数据库onongrade SQLiteException

时间:2018-11-01 16:28:55

标签: android sqlite

我已经实现了将数据库升级到新版本的逻辑。而且一切正常,否则我会崩溃成千上万。 无论如何,每月在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();调用使用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有问题?

1 个答案:

答案 0 :(得分:0)

您是否尝试过将逻辑移至IntentService?广播接收器不应处理长时间的操作,而应仅作为调度程序使用。