У моего приложения одна из основных причин сбоев в отчетах: java.lang.IllegalStateException
Я вижу, откуда оно, это функциональность, которая создает уведомления из БД содержимое в фоновом режиме в течение дня, когда приложение не активно. Интересно то, что это, кажется, происходит только в самой новой Android 10 версии:
Что-то изменилось в как вы обрабатываете данные базы данных в неактивном состоянии приложения?
Вот отчет cra sh:
java.lang.RuntimeException:
at android.os.AsyncTask$4.done (AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:383)
at java.util.concurrent.FutureTask.setException (FutureTask.java:252)
at java.util.concurrent.FutureTask.run (FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
at java.lang.Thread.run (Thread.java:919)
Caused by: java.lang.IllegalStateException:
at androidx.room.RoomOpenHelper.checkIdentity (RoomOpenHelper.java:139)
at androidx.room.RoomOpenHelper.onOpen (RoomOpenHelper.java:119)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen (FrameworkSQLiteOpenHelper.java:151)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked (SQLiteOpenHelper.java:428)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:317)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase (FrameworkSQLiteOpenHelper.java:96)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase (FrameworkSQLiteOpenHelper.java:54)
at androidx.room.RoomDatabase.query (RoomDatabase.java:256)
at androidx.room.util.DBUtil.query (DBUtil.java:54)
(the next 3 lines are where it's at)
at com.dev.solidmind.db.dao.MNotificationDao_Impl.getNextNotification (MNotificationDao_Impl.java:75)
at com.dev.solidmind.repository.NotificationRepository$FetchNextNotifAsyncTask.doInBackground (NotificationRepository.java:58)
at com.dev.solidmind.repository.NotificationRepository$FetchNextNotifAsyncTask.doInBackground (NotificationRepository.java:41)
at android.os.AsyncTask$3.call (AsyncTask.java:378)
at java.util.concurrent.FutureTask.run (FutureTask.java:266)
Что касается кода, у меня есть AlarmManager
который вызывает слушателя в какой-то момент в течение дня. В этом слушателе я вызываю AsyncTask
, который извлекает данные из БД в фоновом режиме и вызывает метод интерфейса, чтобы уведомить слушателя, когда это будет сделано:
public class NotificationReceiver extends BroadcastReceiver implements NotificationRepository.FetchNextNotifAsyncTask.AsyncResponse {
private Context context;
private NotificationRepository repository;
private MessageNotification nextNotification;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong("lastTimeOfNotifTrigger", System.currentTimeMillis());
editor.apply();
repository = new NotificationRepository(context);
repository.startGetNextNotificationAsync(this);
}
@Override
//Callback for when notification object has been retrieved from DB
public void processFinish(MessageNotification notification) {
if (notification != null) {
nextNotification = notification;
constructNotification();
setNextAlarm();
}
}
...
public class NotificationRepository {
private MNotificationDao mNotificationDao;
private SuggestionDao suggestionDao;
public NotificationRepository(Context context) {
AppRoomDatabase db = DatabaseCopier.getInstance(context).getRoomDatabase(); //get db from existing file
mNotificationDao = db.mNotificationDao();
suggestionDao = db.suggestionDao();
}
public void startGetNextNotificationAsync(FetchNextNotifAsyncTask.AsyncResponse delegate) {
new FetchNextNotifAsyncTask(delegate, mNotificationDao).execute();
}
public void setNewNextNotification(int id) {
new UpdateNextNotifAsyncTask(mNotificationDao).execute(id);
}
public void revealSuggestion(int id) {
new UpdateIsRevealedAsyncTask(suggestionDao).execute(id);
}
public void revealPremiumSuggestions() {
new RevealPremiumAsyncTask(suggestionDao).execute();
}
//=== Inner AsyncTask class to run updates in the background ===
public static class FetchNextNotifAsyncTask extends AsyncTask<Void, Void, MessageNotification> {
//Interface delegate to notify Activity when done
public interface AsyncResponse {
void processFinish(MessageNotification notification);
}
private AsyncResponse delegate;
private MNotificationDao mAsyncTaskDao;
FetchNextNotifAsyncTask(AsyncResponse delegate, MNotificationDao dao) {
this.delegate = delegate;
mAsyncTaskDao = dao;
}
@Override
protected MessageNotification doInBackground(Void... voids) {
return mAsyncTaskDao.getNextNotification();
}
@Override
protected void onPostExecute(MessageNotification notification) {
delegate.processFinish(notification);
}
}
...
Я нашел связанные вопросы, но они охватывают другие специфические c аспекты, такие как закрытие диалогов или ClickListener:
IllegalStateException при AsyncTask
IllegalStateException asynctask - onPostExecute
Play Store Cra sh Отчет: IllegalStateException на android .view.View $ DeclaredOnClickListener.onClick
Как указано на странице Android Dev:
Выдает IllegalStateException
Если getStatus () возвращает либо AsyncTask.Status # RUNNING, либо AsyncTask.Status # FINISHED.
Так что, кажется, является причиной? Или, может быть, делегат интерфейса?