Наше приложение может подключаться к устройству HVAC, и ему необходимо каждые 10 секунд выполнять выборку его состояния.
Устройство HVAC предоставляет интерфейс Modbus и выборки буфера CANNOT.Нам на самом деле нужно пробуждать сервис каждые 10 секунд.Типичная пробная сессия длится от 1 часа до нескольких часов.(Существуют различные типы подключения / кабели / мосты: USB-конвертер OTG + RS232, TCP через мост RS232 / TCP, Bluetooth classic и мосты BLE через RS232 / BT или BLE.)
Конечно,пользователь должен иметь возможность отключить дисплей для экономии заряда аккумулятора и перехода к другим приложениям во время сеанса выборки.
До Nougat 7.0 наше рабочее решение было:
- Запустите
IntenService
, затем установите для него Foreground
Сервис - Связанный с этим сервисом, так что это также сервис
Bounded
(чтобы остановить его, распространите взаимодействие с устройством HVAC отGUI и т. Д.) - Получение
PowerManager.PARTIAL_WAKE_LOCK
- Использование
Thread.Sleep()
для цикла 10 секунд, а также для управления тайм-аутами в реализации транспорта различных соединений
Должен ли я разместить код?Соответствующие детали являются наиболее распространенными шаблонами.
Несмотря на отсутствие документированных гарантий, Thread.Sleep()
с PowerManager.PARTIAL_WAKE_LOCK
в Foreground Service работал отлично, пока Nougat 7.0
На нашем тестируемом устройстве Oreo, оба компилируя API 26 и 23 для таргетинга (как наша предыдущая выпущенная версия), при этом не взаимодействуя с действиями приложения (отключение отображения, другие приложения на переднем плане и т. Д.), Сервис не активируется, он спитдо первого взаимодействия с приложением.
Чтобы иметь возможность запускать службу переднего плана на API нацеливания Oreo 26, я реализовал решение Бикрама Пандита из Android O - Старый запуск службы переднего плана все еще работает? ,Ничего не изменилось.
Я запросил исключение Battery Optimizations с ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
(как описано в https://developer.android.com/training/monitoring-device-state/doze-standby#whitelisting-cases) и предоставил его.Ничего не изменилось.(И приложение работало без него до Nougat 7.0)
В документации о предельных значениях фонового выполнения Oreo, https://developer.android.com/about/versions/oreo/background, говорится, что ограниченные службы или службы Foreground не должны подвергаться этим ограничениям.И все же сервис не просыпается.
AlarmManager
не может быть использован, поскольку из Oreo он может срабатывать максимум каждые 9 минут, даже с setAndAllowWhileIdle()
или setExactAndAllowWhileIdle()
.(Опять же в https://developer.android.com/training/monitoring-device-state/doze-standby#whitelisting-cases)
Я также попытался использовать wait(sleepTime)
вместо Thread.sleep()
: еще хуже, он даже не просыпается при возобновлении взаимодействия.
Я остановилсяперед повторной реализацией как JobIntentService
или с использованием JobScheduler
/ JobService
, чтобы переосмыслить каждый образец как задание, но:
- ВАЖНО: мне все равно понадобится
Thread.Sleep()
внекоторые реализации соединений транспортного уровня, это проснется во время работы? - Будет ли
JobScheduler
фактически позволять запускать задания каждые 10 секунд, или это будет связывать их вместе в Oreo? Нам на самом деле нужен пример каждый10 секунд. Вероятно, мы могли бы расслабиться до 1 минуты, но не больше. - Могу ли я сохранить очень сложное состояние (мой объект ModbusDevice) в
JobService
, чтобы разделить его между всеми этими заданиями, иначе будут ограничения?
Опять же, я должен опубликовать какой-нибудь код? Это самый распространенный шаблон.