Таймер Android, который работает, когда устройство спит - PullRequest
13 голосов
/ 07 февраля 2011

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

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

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

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

Спасибо,

Рич

Ответы [ 2 ]

4 голосов
/ 09 февраля 2011

У меня есть частичное решение моего первоначального поста выше. Он еще не учитывает дрейф часов, связанный с временем, потраченным на вычисления при обработке 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 довольно хорошими. Интересно ...

Ура, Рич

0 голосов
/ 31 января 2019

Извините, это не совсем ответ, но я чувствую, что ваш процесс похож на мой, но мало что касалось кода, чтобы прояснить, как вы справились с проблемой сна.У меня нет дрейфа, но приложение зависает, когда оно переходит в спящий режим, затем как бы сбрасывает вперед, когда дисплей активен, затем снова зависает, когда устройство спит.Это ядро ​​процесса таймера.

    Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {

    @Override
    public void run() {

        // do something here to display

        processTime();    // process what to be done on a sec by sec basis
        try {
            timerHandler.postDelayed(this, 1000
        } catch (Exception ex){

        }

    }
};

Есть ли здесь что-то, что я могу сделать, чтобы оно продолжалось в спящем режиме?Это используется для работы на старых версиях Android / устройств.

...