Служба Android работает только при активном пользовательском интерфейсе

Похоже, что Android в последней версии ввел множество ограничений на запуск сервисов в фоновом режиме, что, конечно, является хорошей новостью для времени автономной работы наших устройств. Моя цель состоит в том, чтобы создать приложение, которое придерживается этого, только запуская службу, пока пользователь взаимодействует с приложением (что, по-видимому, и является целью). Но мне совсем не ясно, как вы можете правильно это реализовать. Мои требования следующие:

  • Служба должна быть запущена, как только любая активность станет видимой для пользователя.

  • Служба должна оставаться непрерывной в рабочем состоянии, пока пользователь взаимодействует с приложением (просмотр между действиями).

  • Когда пользовательский интерфейс (независимо от того, какое действие было активным) отправляется в фоновом режиме, служба должна работать в течение 2-3 секунд, а затем останавливаться. 2-3 секунды необходимо для полного отключения услуги.

  • Служба может быть запущена с помощью Push-сообщения, когда приложение находится в фоновом режиме (или закрыто), чтобы обрабатывать входящие события в любое время. Затем служба регистрируется на удаленном сервере и проверяет наличие обновлений. При наличии обновлений пользователю выдается уведомление. Затем служба снова отключается через 2-3 секунды бездействия.

Мне кажется, Bound Service - это то, что предназначено для использования. Но мне не ясно, как мои требования будут соответствовать модели Bound Service. Есть ли кто-нибудь, кто имеет какой-либо опыт с этим, кто может указать мне правильное направление?

РЕДАКТИРОВАТЬ: "Сервис" в этом случае является локальным, внутрипроцессного сервиса, который не предназначен для внешнего доступа.

1 ответ

Решение

(Этот ответ предполагает местное, "в процессе" Service, что не вызывает сомнений, что вы собираетесь использовать.)

Для вашего случая использования вы фактически используете комбинацию методов, чтобы сохранить Service Бег.

Используйте "связаны Service модель "чтобы сохранить Service в то время как любой из ваших Activities видны Это достаточно просто; вызов bindService() в Activity.onStart(), а также unbindService() в Activity.onStop(), Если вы беспокоитесь о Service разрушается в короткий момент перехода между двумя вашими Activitiesне будь; Android достаточно умен, чтобы ждать изменений в жизненном цикле различных компонентов приложения, прежде чем он решит Service не имеет ссылки / не требуется.

Вы должны использовать BIND_AUTO_CREATE флаг для всех ваших bindService() звонки. Имейте в виду, что Service не создается сразу после звонка bindService(); это займет несколько миллисекунд, и вы должны быть осторожны, чтобы вернуть управление в среду, возвращаясь из любого метода жизненного цикла (например, onStart()) вы находитесь в настоящее время. Только тогда вы получите звонок onServiceConnected(),

Вам нужно будет вручную отслеживать, сколько Activities привязаны к вашему Service, чтобы определить, когда начинать свою 2-3-секундную логику очистки. Смотрите этот ответ для правильного подхода. Не беспокойся о Service быть уничтоженным синхронно во время вашего последнего unbindService() вызов - так же, как с bindService()фактическое изменение состояния жизненного цикла "задерживается".

Теперь вопрос в том, как вы храните Service в течение этих дополнительных 2-3 секунд, в этот момент (точка, в которой вы определили количество открытых Activities опустился до 0)? Ну, вы можете просто позвонить startService(), Вы даже можете вызвать его из метода в вашем Service подкласс; до тех пор, пока у вас есть действительный Context доступно, это не имеет большого значения. startService() указывает системе, что вы хотите сохранить Service вокруг, независимо от того, сколько Activities (или другие клиенты) могут быть связаны с этим. В этом случае Service не будет перезапущен - он уже запущен!

После завершения очистки вы можете позвонить stopService() или, еще лучше, stopSelf(), Это эффективно отменяет startService() позвоните, и скажет ОС: "Я сделал". Ожидайте звонок Service.onDestroy() вскоре после этого.

Имейте в виду, что один из ваших Activities может всплыть асинхронно и повторно привязать к Serviceдо завершения очистки. Это крайний случай, но тот, который легко обрабатывается. Service будет уничтожено только в том случае, если выполняются оба этих условия: 1.) ни один клиент не будет привязан / привязан, и 2.) нет неотмененных вызовов startService() существовать.

Обратите внимание, что в Oreo и более поздних версиях система может быть достаточно агрессивной, чтобы убивать приложения в фоновом режиме. Services, Согласно этому документу, взаимодействие с пользователем помещает вас в белый список на "несколько минут", поэтому я думаю, что через 2-3 секунды все будет в порядке. Точно так же, если вы обрабатываете "высокоприоритетное сообщение FCM" (что, как я полагаю, вы подразумеваете под "push-сообщением"), вы попадете в белый список и получите еще несколько минут для выполнения Service (на этот раз используя startService()/stopSelf() подход).

Другие вопросы по тегам