AlarmManager setExact с WakefulBroadcastReceiver иногда не точный

Использование Android 19 +

setExact в соединении с WakefulBroadcastReceiver иногда не срабатывает вовремя (может быть несколько секунд или так поздно). Я имею в виду большую часть времени. вероятно, 49 раз из 50 правильных.

Я не уверен, что это только потому, что система занята в то время и не может обрабатывать рабочую нагрузку или что

Вот как я устанавливаю будильник:

  AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Intent intent = new Intent(AlarmReceiver.INTENT_FILTER);
  PendingIntent alarmIntent = PendingIntent.getBroadcast(context, MyApplication.ALARM_REQUEST_CODE, intent,  PendingIntent.FLAG_UPDATE_CURRENT);
  alarmMgr.setExact(AlarmManager.RTC_WAKEUP, timeToWakeUp, alarmIntent);

Вот мой код приемника:

public class AlarmReceiver extends WakefulBroadcastReceiver {

public static final String INTENT_FILTER = "myfilter";

@Override
public void onReceive(Context context, Intent intent) {
    Intent service = new Intent(context, MyWakefulService.class);
    startWakefulService(context, service);

}

}

И в программе WakefulService

public class MyWakefulService extends IntentService {

....

@Override
protected void onHandleIntent(Intent intent) {

....

Ответ 1

Такое поведение добавляется в API 19:

Начиная с доставки сообщений API 19 (KITKAT) неточно: ОС сбрасывает аварийные сигналы, чтобы свести к минимуму пробуждения и использование батареи. Существуют новые API-интерфейсы для поддержки приложений, требующих строгих гарантий доставки; см. setWindow (int, long, long, PendingIntent) и setExact (int, long, PendingIntent). Приложения, чья targetSdkVersion ранее, чем API 19, будут продолжать видеть предыдущее поведение, при котором все сигналы тревоги отправляются точно по запросу.

из AlarmManager.

Важно: setExact() по-прежнему не обязательно быть точным, поскольку состояние документов:

Тревога будет доставлена ​​как можно ближе к запрошенному времени запуска.

Ответ 2

В эпоху Зефира (?) нам нужны некоторые уродливые коды, например ниже...:( Параметр "delayInMillis" должен быть более 15 минут на API 23. Если нет, система игнорирует минуты менее 15 минут.

private void registerExactAlarm(PendingIntent sender, long delayInMillis) {
    final int SDK_INT = Build.VERSION.SDK_INT;
    AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
    long timeInMillis = (System.currentTimeMillis() + delayInMillis) / 1000 * 1000;     //> example

    if (SDK_INT < Build.VERSION_CODES.KITKAT) {
        am.set(AlarmManager.RTC_WAKEUP, timeInMillis, sender);
    }
    else if (Build.VERSION_CODES.KITKAT <= SDK_INT  && SDK_INT < Build.VERSION_CODES.M) {
        am.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, sender);
    }
    else if (SDK_INT >= Build.VERSION_CODES.M) {
        am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, sender);
    }
}