Подтвердить что ты не робот

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

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

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

Настройка назначения AlarmManager:

        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);

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Возможно, вам помогут:

Если наше приложение нацелено на уровень API ниже 19 (KitKat), запланированные аварийные сигналы будут выполняться точно в тревожное время. Для приложений, ориентированных на KitKat или позже, расписание считается неточным, и система может переупорядочить или сгруппировать аварийные сигналы, чтобы свести к минимуму пробуждения и сэкономить аккумулятор.

После уровня API 23, команда разработчиков Android прошла немного дальше и Doze режим был введен в Android-системе, чтобы уменьшить потребление батареи, когда устройство отсоединяется от адаптера питания, неподвижно и не используется пользователь в течение длительного периода времени.

Система Doze будет пытаться уменьшить отсрочку частоты пробуждения устройства фоновые задания, сетевые обновления, синхронизацию и нашу драгоценную тревогу до тех пор, пока устройство выходит из режима Doose или запускает текущее окно обслуживания для выполнения ожидающие задания, определенные тревоги или синхронизация с сетью. После окна технического обслуживания, устройство снова войдет в режим "Дозировка" если он не использовался в то же время:

введите описание изображения здесь

Режим доз может повлиять на ваше приложение и отложит ваши сигналы тревоги пока не появится окно обслуживания, если вы не используете методы setAndAllowWhileIdle() и setExactAndAllowWhileIdle(), чтобы разрешить выполнение ваших аварийных сигналов в состоянии длительного простоя.

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

В режиме доз приложениям также не разрешается доступ к сети, Wake Wake игнорируются и сканирование Wi-Fi не выполняется.

Если нам нужно точное планирование и вы нацеливаетесь на Зефир или позже, мы будем использовать новый метод setExactAndAllowWhileIdle(), введенный в Уровень API 23:

am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pending);

Примечание:

В системе Android есть защита, которая предотвращает которые часто отключаются. AlarmManager только просыпается устройство и отправляет один сигнал тревоги в минуту, а при малой мощности режим может быть таким же низким, как каждый раз каждые 15 минут.

Если ваше приложение нацелено на версию между KitKat (API-уровень 19) и Marshmallow (API-уровень 23), метода setExact достаточно для точности синхронизации:

am.setExact(AlarmManager.RTC_WAKEUP, time, pending);

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

if (Build.VERSION.SDK_INT >= 23) {
// Wakes up the device in Doze Mode
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time,
pending);
} else if (Build.VERSION.SDK_INT >= 19) {
// Wakes up the device in Idle Mode
am.setExact(AlarmManager.RTC_WAKEUP, time, pending);
} else {
// Old APIs
am.set(AlarmManager.RTC_WAKEUP, time, pending);
}

Это обеспечит наш будильник точно в указанное время на всех платформах.

Асинхронное программирование для Android

Ответ 3

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

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

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