Как проверить, работает ли фоновая служба?
Я хочу, чтобы активность Android изменяла состояние службы - она позволяла мне включать его, если он выключен, и выключен, если он включен.
android
android-service
пчелка
источник
источник
getRunningTasks()
, вероятно, так и будет.Ответы:
У меня была такая же проблема не так давно. Так как мой сервис был локальным, я просто использовал статическое поле в классе сервиса для переключения состояния, как описано здесь hackbod
РЕДАКТИРОВАТЬ (для записи):
Вот решение, предложенное hackbod:
источник
onDestroy()
вызывается. Таким образом, статическая переменная не может быть обновлена в таком сценарии, что приводит к противоречивому поведению.Я использую следующее изнутри деятельности:
И я называю это используя:
Это работает надежно, поскольку основано на информации о запущенных сервисах, предоставляемых операционной системой Android через ActivityManager # getRunningServices .
Все подходы, использующие события onDestroy или onSometing, или Binder, или статические переменные, не будут работать надежно, потому что как разработчик вы никогда не знаете, когда Android решает убить ваш процесс или какой из упомянутых обратных вызовов вызван или нет. Обратите внимание на столбец «killable» в таблице событий жизненного цикла в документации Android.
источник
getRunningServices
является устаревшим. Этот ответ требует обновления для более новой версии.Понял!
Вы ДОЛЖНЫ призвать
startService()
к тому, чтобы ваша служба была должным образом зарегистрирована, и передачиBIND_AUTO_CREATE
не будет достаточно.А теперь класс ServiceTools:
источник
Небольшое дополнение это:
Моя цель - знать, запущен ли сервис без его фактического запуска, если он не запущен.
Вызов bindService или вызов намерения, которое может быть перехвачено службой, не является хорошей идеей, поскольку он запустит службу, если она не запущена.
Итак, как предположил miracle2k, лучше всего иметь статическое поле в классе обслуживания, чтобы знать, запущена служба или нет.
Чтобы сделать его еще чище, я предлагаю преобразовать службу в синглтон с очень и очень ленивым извлечением: т. Е. Вообще нет экземпляра синглтона например , через статические методы. Статический метод getInstance вашего сервиса / синглтона просто возвращает экземпляр синглтона, если он был создан. Но на самом деле он не запускает и не создает экземпляр самого синглтона. Служба запускается только обычными методами запуска службы.
Тогда было бы еще чище изменить шаблон проектирования синглтона, чтобы переименовать запутанный метод getInstance во что-то вроде
isInstanceCreated() : boolean
метода.Код будет выглядеть так:
Это элегантное решение, но оно актуально только в том случае, если у вас есть доступ к классу обслуживания и только для классов, кроме приложения / пакета службы. Если ваши занятия находятся за пределами приложения / пакета службы, вы можете запросить ActivityManager с ограничениями, подчеркнутыми Питером-Яном Ван Робайсом.
источник
Вы можете использовать это (я еще не пробовал это, но я надеюсь, что это работает):
Метод startService возвращает объект ComponentName, если уже есть запущенная служба. Если нет, ноль будет возвращен.
Смотрите публичный абстрактный ComponentName startService (сервис Intent) .
Я думаю, это не похоже на проверку, потому что она запускает службу, поэтому вы можете добавить ее
stopService(someIntent);
под код.источник
if(startService(someIntent) != null)
это проверит,IsserviceRunning
но это также сыграет новый сервис.источник
Выдержка из документов Android :
Думайте об этом взломе как о "пингующем"
Service
. Поскольку мы можем транслировать синхронно, мы можем транслировать и получать результат синхронно в потоке пользовательского интерфейса.Service
Activity
Конечно, во многих приложениях победителем является статическое логическое поле в сервисе, для которого задано значение
true
inService.onCreate()
иfalse
in,Service.onDestroy()
потому что это намного проще.источник
Я немного изменил одно из представленных выше решений, но передал класс вместо общего имени строки, чтобы быть уверенным в сравнении строк, исходящих из одного и того же метода.
class.getName()
а потом
источник
Class<? extends Service>
Правильный способ проверить, работает ли служба, - просто спросить ее. Внедрите в вашу службу BroadcastReceiver, который отвечает на запросы вашей работы. Зарегистрируйте BroadcastReceiver при запуске службы и отмените ее регистрацию при уничтожении службы. Исходя из вашей активности (или любого компонента), отправьте в службу локальную широковещательную рассылку, и если она ответит, вы знаете, что она работает. Обратите внимание на небольшую разницу между ACTION_PING и ACTION_PONG в приведенном ниже коде.
источник
Я просто хочу добавить примечание к ответу @Snicolas. Следующие шаги могут быть использованы для проверки остановки службы с / без вызова
onDestroy()
.onDestroy()
Вызов: перейдите в Настройки -> Приложение -> Запущенные сервисы -> Выберите и остановите сервис.onDestroy()
не вызывается: выберите «Настройки» -> «Приложение» -> «Управление приложениями» -> выберите и «принудительно остановите» приложение, в котором запущена ваша служба. Однако, поскольку ваше приложение здесь остановлено, экземпляры службы также будут остановлены.Наконец, я хотел бы отметить, что упомянутый там подход с использованием статической переменной в синглтон-классе работает для меня.
источник
onDestroy
не всегда вызывается в сервисе, так что это бесполезно!Например: просто запустите приложение еще раз с одним изменением из Eclipse. Приложение принудительно закрывается с помощью SIG: 9.
источник
Прежде всего, вы не должны пытаться связаться с сервисом с помощью ActivityManager. (Обсуждается здесь )
Службы могут работать самостоятельно, быть привязаны к действию или к обоим. Чтобы проверить в Деятельности, работает ли ваша Служба или нет, нужно создать интерфейс (расширяющий Binder), в котором вы объявляете методы, понятные как Службе, так и Службе. Вы можете сделать это, создав собственный интерфейс, где вы объявляете, например, «isServiceRunning ()». Затем вы можете привязать свою активность к своей службе, запустить метод isServiceRunning (), служба проверит себя, работает ли она или нет, и вернет логическое значение вашей активности.
Вы также можете использовать этот метод, чтобы остановить службу или взаимодействовать с ней другим способом.
Я использовал этот учебник, чтобы узнать, как реализовать этот сценарий в моем приложении.
источник
Опять же, еще одна альтернатива, которую люди могут найти чище, если они используют ожидающие намерения (например, с помощью
AlarmManager
:Где
CODE
константа, которую вы определяете в частном порядке в своем классе, чтобы определить ожидающие намерения, связанные с вашим сервисом.источник
Ниже приведен элегантный хак, который охватывает все
Ifs
. Это только для местных услуг.А потом позже:
источник
Xamarin C # версия:
источник
GetSystemService
.Для приведенного здесь варианта использования мы можем просто использовать
stopService()
возвращаемое значение метода. Он возвращает,true
если существует указанный сервис, и он убит. Остальное возвращаетсяfalse
. Таким образом, вы можете перезапустить службу, если в результатеfalse
получится уверенность, что текущая служба была остановлена. :) Было бы лучше, если вы посмотрите на это .источник
Другой подход с использованием котлина. Вдохновленные другими пользователями ответы
Как расширение котлин
Применение
источник
В kotlin вы можете добавить логическую переменную в объект-компаньон и проверить ее значение из любого класса, который вы хотите:
Измените это значение, когда служба создана и уничтожена
источник
В вашем подклассе службы используйте статическое логическое значение, чтобы получить состояние службы, как показано ниже.
MyService.kt
MainActivity.kt
источник
Для kotlin вы можете использовать приведенный ниже код.
источник
Звонок
источник
ActivityManager.getRunningServices
устарела с Android OМожет быть несколько служб с одинаковым именем класса.
Я только что создал два приложения. Имя пакета первого приложения
com.example.mock
. Я создал подпакетlorem
в приложении и сервис под названиемMock2Service
. Таким образом, его полностью квалифицированное имяcom.example.mock.lorem.Mock2Service
.Затем я создал второе приложение и сервис под названием
Mock2Service
. Название пакета второго приложенияcom.example.mock.lorem
. Полное название услуги:com.example.mock.lorem.Mock2Service
тоже.Вот мой вывод logcat.
Лучшая идея - сравнить
ComponentName
примеров , посколькуequals()
изComponentName
сравнения как имена пакетов и имена классов. И на устройстве не может быть установлено два приложения с одинаковым именем пакета.Метод equals ()
ComponentName
.ComponentName
источник
Пожалуйста, используйте этот код.
источник
Это в большей степени относится к отладке Intent Service, поскольку они порождают поток, но могут работать и для обычных сервисов. Я нашел эту тему благодаря Binging
В моем случае я поиграл с отладчиком и нашел представление потока. Это выглядит как значок маркера в MS Word. В любом случае, вам не нужно находиться в режиме отладчика, чтобы использовать его. Нажмите на процесс и нажмите на эту кнопку. Любые Intent Services будут отображаться во время работы, по крайней мере, на эмуляторе.
источник
Если служба принадлежит другому процессу или APK, используйте решение на основе ActivityManager.
Если у вас есть доступ к его источнику, просто используйте решение на основе статического поля. Но вместо использования логического значения я бы предложил использовать объект Date. Пока служба работает, просто измените ее значение на «сейчас», а когда оно завершится, установите значение «ноль». Из действия вы можете проверить, является ли его ноль или дата слишком старой, что будет означать, что она не запущена.
Вы также можете отправить широковещательное уведомление от вашего сервиса, указывающее, что он работает вместе с дополнительной информацией, такой как прогресс
источник
Внутри TheServiceClass определяют:
Тогда в onStartCommand (...)
Затем позвоните
if(TheServiceClass.serviceRunning == true)
из любого класса.источник
stopService
. По крайней мере, для услуг Intent.onDestroy()
будет вызван немедленно, ноonHandleIntent()
все еще будет запущенпростое использование связать с не создавать авто- см. пс. и обновить ...пример :
почему не используете? getRunningServices ()
Примечание: этот метод предназначен только для отладки или реализации пользовательских интерфейсов типа управления услугами.
пс. Документация Android вводит в заблуждение. Я открыл проблему на Google Tracker, чтобы устранить любые сомнения:
https://issuetracker.google.com/issues/68908332
как мы можем видеть, служба связывания фактически вызывает транзакцию через привязку ActivityManager через привязки кеша службы - я отслеживаю, какая служба отвечает за привязку, но, как мы видим, результат для привязки:
Транзакция производится через связующее:
следующий:
это устанавливается в ActivityThread через:
это вызывается в ActivityManagerService в методе:
тогда:
но нет "активности", только окно пакета и будильник ..
поэтому нам нужно вернуться, чтобы позвонить:
это делает вызов через:
что приводит к :
а это родной метод ....
у меня сейчас нет времени копаться в с, так что пока я не проанализирую покой, я приостановлю свой ответ.
но лучший способ проверить, работает ли сервис это создать привязку (если привязка не создана, служба не существует) - и запросить службу о ее состоянии через привязку (используя хранимый внутренний флаг для этого состояния).
обновление 23.06.2018
я нашел эти интересные:
короче говоря :)
«Предоставьте привязку для уже связанной службы. Этот метод является синхронным и не запускает целевую службу, если она отсутствует».
public IBinder peekService (Служба намерений, String resolvedType, String callPackage) выдает RemoteException;
источник
Мой kotlin преобразование
ActivityManager::getRunningServices
основанных ответов. Поместите эту функцию в активностьисточник
Вы можете использовать эту опцию из опций Android Developer, чтобы увидеть, работает ли ваша служба в фоновом режиме.
источник
Полегче, ребята ... :)
Я думаю, что наиболее подходящим решением является удержание пары ключ-значение в
SharedPreferences
том, запущена служба или нет.Логика очень прямая; на любой желаемой позиции в вашем классе обслуживания; укажите логическое значение, которое будет для вас указывать, работает ли служба. Затем прочитайте это значение везде, где вы хотите в своем приложении.
Пример кода, который я использую в своем приложении, приведен ниже:
В моем классе обслуживания (услуга для аудиопотока) я выполняю следующий код, когда служба работает;
Затем в любой активности моего приложения я проверяю статус сервиса с помощью следующего кода;
Никаких специальных разрешений, никаких петель ... Простой способ, чистое решение :)
Если вам нужна дополнительная информация, пожалуйста, обратитесь по ссылке
Надеюсь это поможет.
источник
onDestroy
не всегда вызывается, когда служба убита. Например, я видел, как мои службы убивали в ситуациях с нехваткой памяти безonDestroy
вызова.