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

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)

4b9b3361

Ответ 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. Уход, ставящий его в манифест, может не помочь.