SetExactAndAllowWhileIdle - не является точным по ссылке разработчика
AlarmManager на API19 имеет метод setExact(), чтобы установить точный сигнал тревоги.
Точные средства → Если я установил будильник до 2:01 вечера, он будет запущен в 2:01 вечера
В API 23 - Marhsmwallow (6.0) появился новый метод setExactAndAllowWhileIdle(), но по ссылке он не является EXACT, потому что он будет запускать только каждую минуту, а в режиме холостого хода - только каждые 15 минут.
Точный!= каждые 15 минут: -)
Итак, как я могу добиться точной тревоги с AlarmManager в 6.0?
Если пользователь добавляет напоминание или назначение календаря и хочет быть проинформирован за 10 минут до события, он должен показать аварийный сигнал ТОЧНО за 10 минут до. С setExactAndAllowWhileIdle() это кажется невозможным.
Ссылка:
http://developer.android.com/reference/android/app/AlarmManager.html#setExactAndAllowWhileIdle (int, long, android.app.PendingIntent)
Ответы
Ответ 1
Итак, как я могу достичь точной тревоги с AlarmManager в 6.0?
Вы можете попробовать setAlarmClock()
, поскольку AFAIK не зависит от режима Doze. В противном случае AlarmManager
не является жизнеспособным вариантом для вас. Даже наличие вашего приложения в белом списке оптимизации батареи не поможет, так как поведение AlarmManager
не изменяется в зависимости от белого списка.
Вы можете использовать GCM, так как высокоприоритетное сообщение должно дать вам возможность предупредить пользователя. Это, конечно же, требует подключения к сети.
Единственное автономное решение, которое я знаю о — и что я в настоящее время тестирую — заключается в том, чтобы пользователь добавил ваше приложение в белый список оптимизации батареи, затем использовал переднюю службу (чтобы попытаться сохранить процесс), ScheduledExecutorService
(для синхронизации) и частичный WakeLock
(чтобы сохранить процессор на). Это будет довольно разрушительно для аккумулятора пользователя.
Ответ 2
Использование setExactAndAllowWhileIdle() для одноразового будильника будет срабатывать точно в указанное время даже в режиме ожидания Doze. Так что это, вероятно, путь.
Проблемы начинаются, если вы хотите повторить сигнал тревоги со скоростью < 15 минут (или установить любой другой за один раз и менее 15 минут от последнего), так как это не будет работать в режиме ожидания Doze, где такие сигналы тревоги будут выведены на следующие 15 минут или будут выполняться при запуске простоя, что происходит примерно десять минут сначала через 1 час, затем через 2 часа, затем через 4 часа и т.д.
- EDIT -
На сегодняшний день, 17 ноября, Dianne Hackborn пишет в этот пост:
"Для того, что стоит, минимальное время между ожиданиями в режиме ожидания будет немного изменено до 9 минут (даже на устройствах, на которых работают текущие сборки Marshmallow).
Это ничего не меняет, хотя.
Ответ 3
Вот моя дискуссия с Яном Озеро в Google +!
setExactAndAllowWhileIdle() является точным и должен работать.
15-минутный временной интервал неверен в документе java.
![введите описание изображения здесь]()
Ответ 4
Я обнаружил, что до сих пор лучшим вариантом является использование SyncAdapter, который расширяет AbstractThreadedSyncAdapter. Я планирую, чтобы он автоматически продолжал выполнять мой код с требуемым интервалом:
ContentResolver.setSyncAutomatically(account, AUTHORITY, true);
ContentResolver.addPeriodicSync(account, AUTHORITY, settingsBundle, syncInterval);
Ответ 5
Я пытался создать систему автоматизации, работающую в фоновом режиме. Мой диапазон частот составлял от 1 до 15 минут. Мое желание состояло в том, чтобы не использовать службу переднего плана. Изучив имя метода "setExactAndAllowWhileIdle", я подумал, что безопасно идти с одноразовыми аварийными сигналами, планируя следующий, когда это будет сделано.
Однако я не мог найти способ запускать код в режиме доз, при котором сигналы тревоги работают чаще, чем 15 минут. Вместо этого я выбираю запуск переднего плана, когда режим доз активируется и останавливается, что переднего плана при пробуждении телефона. Пользователь не будет видеть ваше уведомление переднего плана при использовании своего телефона. Мне все равно, что в режиме доз.
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(intent.getAction().equals("android.os.action.DEVICE_IDLE_MODE_CHANGED")){
if (pm.isDeviceIdleMode()) {
//startAutomationForegroundService();
} else {
//stopAutomationForegroundService();
return;
}
AutomationReceiver.completeWakefulIntent(intent);
return;
}
}
Вам необходимо зарегистрировать фильтр "android.os.action.DEVICE_IDLE_MODE_CHANGED" в свой WakemarkBroadcastReceiver. Уход, ставящий его в манифест, может не помочь.