В моем приложении я использую AlarmManager, чтобы запустить IntentService, который обращается к внутренней базе данных котировок и выбирает один случайным образом, а затем генерирует уведомление с этой цитатой.
Он отлично работает на моем телефоне, который Android 9, OnePlus6. Но я получаю много данных о сбоях от других пользователей, заявляющих:
Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.myapp.receiver.AlarmReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.myapp/.service.NotificationQuoteService }: app is in background uid UidRecord{e3c2e3d u0a203 TRNB idle procs:1 proclist:23491, seq(0,0,0)}
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3606)
at android.app.ActivityThread.access$1300(ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1796)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7045)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
Полагаю, это вызвано тем ограничением, которое имеет Oreo, что каждая фоновая задача должна уведомлять себя через уведомление переднего плана. Однако не было бы абсурдом показывать уведомление на переднем плане для запроса кавычек, а затем показывать уведомление о кавычках ?! Существует множество приложений, которые делают аналогичные вещи, они запрашивают внутренние данные и показывают их в уведомлении, не показывая никаких уведомлений переднего плана во время запроса данных.
Как бы я это сделал, может кто-нибудь направить меня в нужном направлении?
РЕДАКТИРОВАТЬ Коды добавлены:
AlarmManager для go выключен в 9 утра .
private void prepareAlarmManager() {
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, AlarmReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
if (alarmManager != null) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 9);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent);
}
}
BroadcastReceiver для обработки AlarmManager
public class AlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 10;
@Override
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, NotificationQuoteService.class);
context.startService(serviceIntent);
}
}
IntentService для запроса внутренней базы данных SQLite и уведомления о пожаре
public class NotificationQuoteService extends IntentService {
private Context mContext;
private DatabaseHelper mDatabaseHelper;
public NotificationQuoteService() {
super("quote service");
}
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
mDatabaseHelper = DatabaseHelper.getInstance(mContext);
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
List<Quote> quoteList = mDatabaseHelper.getAllQuotes();
int size = quoteList.size();
int randomIndex = (int) (Math.random() * size);
Quote quote = quoteList.get(randomIndex);
NotificationHelper.showDefaultNotification(mContext, quote);
}
@Override
public void onDestroy() {
super.onDestroy();
L.e("hop", "service is destroyed");
}
}