Как заставить 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);
Некоторые из методов были вставлены в ряд для упрощения чтения.
Ответы
Ответ 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 секунд, чтобы это приложение для получения дополнительных блокировок слежения, в которые можно завершить его работы.