Таймер Android, который работает, когда устройство спит

Я пишу спортивное приложение, которое должно отслеживать прошедшее время квартала / половины / периода. Истекшее время должно быть точным для второго. Часы игры должны продолжать работать, даже если пользователь явно помещает устройство в спящий режим, нажав кнопку питания.

Моя первая попытка в этом заключалась в использовании Handler.postDelayed (), чтобы вызвать тактику часов каждые 200 мс и WindowManager.LayoutParms.FLAG_KEEP_SCREEN_ON, чтобы гарантировать, что «часы» не были остановлены таймаутом экрана. Но вскоре я узнал, что можно обойти этот подход, нажав кнопку питания, чтобы вручную перевести устройство в режим сна. Кроме того, метод postDelayed () испытывает некоторый дрейф синхронизации, по-видимому, результат времени, затраченного на метод run (). Фактические цифры по-прежнему точны, но вместо выравнивания, например, на 5-секундных границах, которые легко понятны пользователям – задействованные таймеры начинают дрейфовать, что приводит к некоторой понятной путанице пользователя.

После небольшого исследования я нашел техники для использования сервисов, таймеров java , AlarmManager и PartialWakeLock для реализации таймеров. Сервисы сами по себе не решают проблему, связанную с переходом устройства в режим сна. Таймеры Java, такие как службы, не решают проблему с устройством, которое будет спать. AlarmManager кажется хорошим подходом, но я обеспокоен тем, что это неправильное использование AlarmManager (т. Е. Очень короткие интервалы между сигналами тревоги). Использование PartialWakeLock также выглядит многообещающим, но само по себе оно не касается проблемы с дрейфом часов, с которой я столкнулся.

Я собираюсь попробовать сочетание AlarmManager и PartialWakeLock. Идея состоит в том, что AlarmManager поможет бороться с дрейфом часов и PartialWakeLock, чтобы упростить прохождение кода (скрестив пальцы). Я надеюсь, что такой подход приведет к разумному балансу между энергосбережением, сложностью кода и ожиданиями пользователей. Любые советы высоко ценится.

Благодаря,

Богатые

У меня есть частичное решение для моего первоначального поста выше. Он еще не обращается к дрейфу часов, связанному с временем, проведенным в вычислениях во время обработки postDelayed () , но это шаг вперед. Кроме того, это обманчиво просто, всегда хороший знак.

Оказывается, я использовал SystemClock.uptimeMillis (), когда я должен был использовать SystemClock.elapsedRealtime () . Разница между двумя является тонкой, но важной.

Как и следовало ожидать, мое решение отслеживает прошедшее время, накапливая длительность между вызовами postDelayed () – т.е. прошедшее время = elapsedTime + lastClockInterval . Как указано выше, первоначальная реализация использовала uptimeMillis () . Тщательное считывание javadoc показывает, что uptimeMillis () не включает время, затрачиваемое на «глубокий сон», например, когда пользователь нажимает кнопку питания. Но метод elapsedRealtime () включает время, проведенное в режиме «глубокого сна». Все, что требовалось для отслеживания времени в глубоких циклах сна, заключалось в замене использования uptimeMillis () с помощью elapsedRealtime () . Успех! Нет необходимости использовать AlarmManager, PartialWakeLock или что-то еще существенно более сложное. Разумеется, эти методы все еще используют, но они чрезмерны при реализации простых истекших часов или таймера.

Следующая проблема для решения – это дрифт часов, вызванный ненулевым временем выполнения, связанным с обработкой postDelayed () . Я надеюсь, что создание нереста для обработки приведет к этой проблеме, позволяя postDelayed () более или менее имитировать асинхронный вызов. Другим подходом было бы настроить время задержки postDelayed (), чтобы учесть время, потраченное на postDelayed () . Я опубликую свои результаты.

На несвязанной ноте, во время моего расследования я относился к CommonsWare Warescription . Хотя я не использовал напрямую идеи из этого источника для этой проблемы, я действительно думаю, что это будет мой Android-источник информации для обозримого будущего. У меня есть подписка O'Reilly через мою дневную работу, но я обнаружил, что книги CommonsWare были как минимум полезными, если не лучшими, источником информации о разработке Android в качестве ресурсов O'Reilly. И я нашел ресурсы O'Reilly Safari довольно хорошими. Интересно…

Приветствия, богатые