Как заставить Alarm Manager работать, когда Android 6.0 в режиме Doze?

Я разработчик двух приложений будильника в Google Play. Я пытаюсь заставить их работать с Android 6.0. Тем не менее, режим Doze делает так, чтобы они не звонили. Я помещаю их в белый список, я поднимаю значок уведомления на переднем плане, я не уверен, что еще я могу сделать - когда в режиме ожидания, сигналы тревоги диспетчера аварий по-прежнему игнорируются. Однако приложение "Часы" (скорее, Google Play, чем AOSP) отличается. Когда будильник включен в приложении "Часы", "adb deviceidle step" всегда будет читать "active" и никогда не "idle", "idle_pending" или что-либо еще.

Android обманывает здесь, придавая собственному приложению больше возможностей, иначе. "тянуть яблоко"? Все приложения с будильниками в Google Play станут неработоспособными? Как-то здесь беспокоит то, что это качественные приложения, каждое из которых заняло год на частичную занятость, и для меня это большой источник дохода. Любые подсказки о том, как я мог заставить их работать, были бы огромной помощью.

Установка намерения Alarm Manager:

        Intent intent = new Intent(context, ReceiverAlarm.class);
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        }
        amSender = PendingIntent.getBroadcast(context, 1, intent, PendingIntent.FLAG_CANCEL_CURRENT); //FLAG_CANCEL_CURRENT seems to be required to prevent a bug where the intent doesn't fire after app reinstall in KitKat
        am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, scheduleToTime+1, amSender);

и класс ReceiverAlarm:

public class ReceiverAlarm extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {
    if (wakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
        wakeLock.acquire();
    }
    X.alarmMaster.startRingingAlarm(true);
}

и соответствующие части метода X.alarmMaster.startRingingAlarm():

    if (wakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Theme.appTitle);
        wakeLock.acquire();
    }

    if (screenWakeLock == null) {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        screenWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE, Theme.appTitle+" scr");
        screenWakeLock.acquire();
    }

    Intent alarmIntent = new Intent(Intent.ACTION_VIEW);
    alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    alarmIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    alarmIntent.setClass(context, ActivityAlarmAlarm.class);

    context.startActivity(alarmIntent);

Некоторые из методов были вставлены в строку для удобства чтения.

2 ответа

Решение

Doze и App Standby определенно изменяют поведение в отношении сигналов тревоги и вейк-шоков, но они определенно не конец света для вас!

Вы пытались использовать метод setAlarmclock() вместо set()? Он разработан специально для будильников и может пробиться сквозь дозу. Существует несколько команд adb, которые вы можете использовать, чтобы вручную перевести телефон в режим ожидания или режим ожидания приложения: https://developer.android.com/preview/features/power-mgmt.html

Если это не может разбудить ваше приложение, есть верный метод setExactAndAllowWhileIdle() предназначен для того, чтобы разбудить телефон от дремоты, несмотря ни на что. В худшем случае вы можете разбудить свое приложение этим методом и использовать пробуждение, чтобы запланировать следующий сигнал тревоги.

Еще одна страница, которую стоит прочитать, - это сообщение в блоге с блок-схемой для фоновой работы и предупреждений: https://plus.google.com/+AndroidDevelopers/posts/GdNrQciPwqo

Поместить приложение в белый список разрешает только сеть в режиме ожидания. AlarmManager не зависит от белого списка.

Для метода setExactAndAllowWhileIdle() проверьте приведенное ниже описание из SDK. Это не разбудит телефон от дремоты.

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

Другие вопросы по тегам