| servicemanager
Менеджер службы Тип файла: служба Комментарии
Служба — это компонент приложения, представляющий либо желание приложения выполнить более длительную операцию, не взаимодействуя с пользователем, либо предоставить функциональность для использования другими приложениями.
Каждый класс обслуживания должен иметь соответствующее <service> объявление в файле AndroidManifest.xml.
Службы можно запустить с помощью Context.startService()и Context.bindService().
Обратите внимание, что службы, как и другие объекты приложения, выполняются в основном потоке своего хост-процесса.
Это означает, что если ваша служба собирается выполнять какие-либо операции с интенсивным использованием ЦП (например, воспроизведение MP3) или блокировку (например, сетевые операции), она должна создать собственный поток, в котором будет выполнять эту работу.
Дополнительную информацию об этом можно найти в разделе «Процессы и потоки» .
Класс JobIntentServiceдоступен как стандартная реализация Service, имеющая собственный поток, в котором он планирует выполнение своей работы.
Большая часть путаницы в отношении класса Service на самом деле связана с тем, чем он не является :
Служба не является отдельным процессом.
Сам объект Службы не означает, что он выполняется в собственном процессе;
если не указано иное, он выполняется в том же процессе, что и приложение, частью которого он является.
Служба не является потоком.
Это не средство само по себе для работы вне основного потока (во избежание ошибок «Приложение не отвечает»).
аким образом, сама Служба на самом деле очень проста и предоставляет две основные функции:
1. Возможность приложения сообщить системе о том, что оно хочет делать в фоновом режиме (даже когда пользователь не взаимодействует с приложением напрямую). Это соответствует вызовам Context.startService(), которые просят систему запланировать работу службы до тех пор, пока служба или кто-то другой явно не остановит ее.
2. Возможность приложения предоставлять часть своих функций другим приложениям. Это соответствует вызовам Context.bindService(), что позволяет установить долговременное соединение со службой для взаимодействия с ней.
Когда компонент службы фактически создается по любой из этих причин, все, что на самом деле делает система, — это создает экземпляр компонента и вызывает его onCreate()и любые другие соответствующие обратные вызовы в основном потоке.
Служба должна реализовать их с соответствующим поведением, например созданием вторичного потока, в котором она выполняет свою работу.
Обратите внимание: поскольку служба сама по себе настолько проста, вы можете сделать свое взаимодействие с ней настолько простым или сложным, насколько захотите: от обработки его как локального объекта Java, к которому вы выполняете прямые вызовы метода (как показано в примере локального сервиса), до предоставления полный удаленный интерфейс с использованием AIDL.
ЖИЗНЕННЫЙ ЦИКЛ СЛУЖБЫ
Есть две причины, по которым служба может запускаться системой.
Если кто-то вызовет Context.startService(), система получит службу (создаст ее и вызовет ее onCreate()метод, если необходимо), а затем вызовет ее onStartCommand(Intent, int, int)метод с аргументами, предоставленными клиентом.
В этот момент служба продолжит работу до тех пор, пока не будет вызвана Context.stopService()или stopSelf().
Обратите внимание, что множественные вызовы Context.startService() не вкладываются (хотя они приводят к множественным соответствующим вызовам onStartCommand()), поэтому независимо от того, сколько раз он запускается, служба будет остановлена после того, как Context.stopService() или stopSelf () называется;
однако службы могут использовать свой метод stopSelf(int), чтобы гарантировать, что служба не будет остановлена до тех пор, пока не будут обработаны запущенные намерения.
Для запущенных служб существует два дополнительных основных режима работы, которые они могут использовать в зависимости от значения, возвращаемого функцией onStartCommand():
START_STICKYиспользуется для служб, которые явно запускаются и останавливаются по мере необходимости
START_NOT_STICKY или START_REDELIVER_INTENTиспользуются для служб, которые должны продолжать работать только во время обработки любых отправленных им команд.
Клиенты также могут использовать его Context.bindService() для получения постоянного подключения к службе.
Это также создает службу, если она еще не запущена (вызывает onCreate()при этом), но не вызывает onStartCommand().
Клиент получит IBinderобъект, который служба возвращает из своего onBind(Intent)метода, что позволит ему затем совершать обратные вызовы службы.
Служба будет работать до тех пор, пока установлено соединение (независимо от того, сохраняет ли клиент ссылку на IBinder службы).
Обычно возвращаемый IBinder предназначен для сложного интерфейса, написанного на Aidl .
Служба может быть как запущена, так и иметь привязанные к ней соединения.
В таком случае система будет поддерживать работу службы до тех пор, пока она запущена или существует одно или несколько подключений к ней с Context.BIND_AUTO_CREATE флагом.
Если ни одна из этих ситуаций не выполняется, вызывается метод службы onDestroy(), и служба фактически завершается.
Вся очистка (остановка потоков, отмена регистрации получателей) должна быть завершена после возвращения из onDestroy().
РАЗРЕШЕНИЯ
Глобальный доступ к службе может быть обеспечен, если он объявлен в теге ее манифеста <service> .
При этом другим приложениям потребуется объявить соответствующий <uses-permission> элемент в своем собственном манифесте, чтобы иметь возможность запускать, останавливать службу или привязываться к ней.
Начиная с Build.VERSION_CODES.GINGERBREAD, при использовании Context.startService(Intent)вы также можете установить Intent.FLAG_GRANT_READ_URI_PERMISSIONи/или Intent.FLAG_GRANT_WRITE_URI_PERMISSIONнамерение.
Это предоставит Службе временный доступ к конкретным URI в намерении. Доступ будет сохраняться до тех пор, пока Служба не вызовет stopSelf(int)эту или более позднюю команду запуска или пока Служба не будет полностью остановлена.
Это работает для предоставления доступа другим приложениям, которые не запрашивали разрешение, защищающее Службу, или даже когда Служба вообще не экспортируется.
Кроме того, служба может защищать отдельные вызовы IPC с помощью разрешений, вызывая метод ContextWrapper.checkCallingPermission(String) перед выполнением реализации этого вызова.
Дополнительную информацию о разрешениях и безопасности в целом см. в документе «Безопасность и разрешения ».
ЖИЗНЕННЫЙ ЦИКЛ ПРОЦЕССА
Система Android будет пытаться поддерживать процесс размещения службы до тех пор, пока служба запущена или к ней привязаны клиенты. При нехватке памяти и необходимости завершить существующие процессы приоритет процесса, размещающего службу, будет выше из следующих возможностей:
Если служба в настоящее время выполняет код в своих методах onCreate(), onStartCommand()или onDestroy(), то хост-процесс будет процессом приоритетного плана, чтобы гарантировать, что этот код может выполняться без прерывания.
Если служба запущена, то ее хост-процесс считается менее важным, чем любые процессы, которые в данный момент видны пользователю на экране, но более важным, чем любой невидимый процесс. Поскольку пользователю обычно видны только несколько процессов, это означает, что службу нельзя завершать, за исключением случаев нехватки памяти. Однако, поскольку пользователь напрямую не знает о фоновой службе, в этом состоянии она считается подходящим кандидатом на уничтожение, и вы должны быть готовы к тому, что это произойдет. В частности, вероятность завершения работы долго работающих служб будет возрастать, и они гарантированно будут прекращены (и перезапущены, если это необходимо), если они будут оставаться запущенными достаточно долго.
Если к службе привязаны клиенты, то процесс размещения службы никогда не менее важен, чем самый важный клиент. То есть если один из его клиентов виден пользователю, то видимым считается и сам сервис. То, как важность клиента влияет на важность услуги, можно регулировать с помощью Context#BIND_ABOVE_CLIENT, Context#BIND_ALLOW_OOM_MANAGEMENT, Context#BIND_WAIVE_PRIORITY, Context#BIND_IMPORTANTи Context#BIND_ADJUST_WITH_ACTIVITY.
Запущенная служба может использовать startForeground(int, android.app.Notification) API для перевода службы в состояние переднего плана, когда система считает, что это что-то, о чем пользователь активно знает, и, следовательно, не является кандидатом на уничтожение при нехватке памяти. Теоретически служба все еще может быть закрыта из-за чрезмерной нехватки памяти из-за текущего приоритетного приложения, но на практике это не должно вызывать беспокойства.
Обратите внимание: это означает, что большую часть времени работы вашей службы она может быть прекращена системой, если она испытывает сильную нехватку памяти. Если это произойдет, система позже попытается перезапустить службу. Важным следствием этого является то, что если вы реализуете onStartCommand() планирование работы, которая будет выполняться асинхронно или в другом потоке, вы можете захотеть использовать START_FLAG_REDELIVERYсистему для повторной доставки намерения для вас, чтобы оно не потерялось, если ваша служба убит во время обработки.
Другие компоненты приложения, работающие в том же процессе, что и служба (например, Activity), конечно, могут повысить важность всего процесса, выходя за рамки важности самой службы.
ОБРАЗЕЦ МЕСТНОЙ СЛУЖБЫ
Одним из наиболее распространенных вариантов использования Службы является использование ее в качестве вторичного компонента, работающего вместе с другими частями приложения в том же процессе, что и остальные компоненты. Все компоненты .apk выполняются в одном и том же процессе, если явно не указано иное, поэтому это типичная ситуация.
При таком использовании, предполагая, что компоненты находятся в одном и том же процессе, вы можете значительно упростить взаимодействие между ними: клиенты службы могут просто привести полученный от нее IBinder к конкретному классу, опубликованному службой.
|
|