Ошибка диспетчера аварий в режиме Android 6.0 Doze

Я сделал приложение, которое всегда работало до Android 6.0. Я думаю, что это функция Doze, которая не позволяет моей тревоги срабатывать.

Я использую sharedpreferences для обработки опций:

//ENABLE NIGHT MODE TIMER
    int sHour = blockerTimerPreferences.getInt("sHour", 00);
    int sMinute = blockerTimerPreferences.getInt("sMinute", 00);

    Calendar sTime = Calendar.getInstance();
    sTime.set(Calendar.HOUR_OF_DAY, sHour);
    sTime.set(Calendar.MINUTE, sMinute);

    Intent enableTimer = new Intent(context, CallReceiver.class);
    enableTimer.putExtra("activate", true);
    PendingIntent startingTimer = PendingIntent.getBroadcast(context, 11002233, enableTimer, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager sAlarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    sAlarm.setRepeating(AlarmManager.RTC_WAKEUP,
            sTime.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, startingTimer);

Любой ключ, что здесь не так?

Это приложение для блокировки звонков. Спасибо!

РЕДАКТИРОВАТЬ: У меня есть 3 файла (больше, но...), как:

MainActivity (All code)
CallReceiver (Broadcast that triggers the alarm again (reboot etc))
CallReceiverService (Handles the call / phone state)

2 ответа

Решение

Режим ожидания будет задерживать вашу тревогу до следующего окна обслуживания. Чтобы избежать режима ожидания, чтобы заблокировать ваш будильник, вы можете использовать setAndAllowWhileIdle(), setExactAndAllowWhileIdle() или же setAlarmClock(), У вас будет около 10 секунд для выполнения вашего кода и установки следующего сигнала тревоги (не чаще, чем один раз в 15 минут для методов с _AndAllowWhileIdle хоть)

Если вы хотите проверить режим Doze, вы можете использовать команду ADB:

  1. Сконфигурируйте аппаратное или виртуальное устройство с системным образом Android 6.0 (уровень API 23) или выше.

  2. Подключите устройство к компьютеру для разработки и установите приложение.

  3. Запустите приложение и оставьте его активным.
  4. Выключите экран устройства. (Приложение остается активным.) Заставьте систему переключаться между режимами Doze, выполнив следующие команды:

    adb shell dumpsys battery unplug

    adb shell dumpsys deviceidle step

  5. Возможно, вам придется выполнить вторую команду более одного раза. Повторяйте это, пока состояние устройства не изменится на режим ожидания.

  6. Наблюдайте за поведением вашего приложения после повторной активации устройства. Убедитесь, что приложение корректно восстанавливается, когда устройство выходит из Doze.

Изменить: Добавить пример setAlarmClock

Не забудьте проверить уровень SDK (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)

AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, MyAlarmReceiver.class); //or just new Intent() for implicit intent 
//set action to know this come from the alarm clock
intent.setAction("from.alarm.clock");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Alarm fire in 5s.
am.setAlarmClock(new AlarmManager.AlarmClockInfo(System.currentTimeMillis() + 5000, pi), pi);

Если устройство находится в режиме ожидания, вам необходимо использовать один из следующих API: setExactAndAllowWhileIdle или setAndAllowWhileIdle.

Обратите внимание, что нет API для пробуждения устройства в режиме ожидания для повторяющегося сигнала, поэтому, если вам нужен повторяющийся сигнал для пробуждения устройства в режиме ожидания, вы должны использовать API выше и перезапускать таймер при каждом появление таймера стрельбы.