Полный список
— передаем данные в сервис
— рассматриваем методы остановки сервиса stopSelf и stopSelfResult
В прошлом уроке мы использовали в коде метод stopSelf. Он вызывается внутри сервиса и останавливает этот сервис. У этого метода есть еще пара вариаций: stopSelf(int startId) и stopSelfResult(int startId). Как видим, на вход они требуют некий startId. Что это и откуда его взять? Для ответа на вопрос давайте взглянем на входящие параметры метода onStartCommand:
Первый – это Intent. Тот самый, который отправляется в путь, когда мы стартуем сервис с помощью метода startService. Соответственно вы можете использовать его для передачи данных в ваш сервис. Тут все аналогично, как при вызове другого Activity – там вы тоже можете передать данные с помощью intent.
Второй параметр – флаги запуска. Он нам пока не нужен, пропускаем его.
Третий параметр – startId. Простыми словами – это счетчик вызовов startService пока сервис запущен. Т.е. вы запустили сервис методом startService, сработал метод onStartCommand и получил на вход startId = 1. Вызываем еще раз метод startService, сработал метод onStartCommand и получил на вход startId = 2. И так далее. Счетчик сбрасывается, когда сервис будет остановлен методами stopService, stopSelf и пр. После этого вызовы снова идут с единицы.
Именно этот startId и нужен на вход методу stopSelf(startId). Т.е. этот метод дает системе понять, что конкретный вызов сервиса был успешно обработан. И мне кажется логичным, что, когда все вызовы сервиса выполнили метод stopSelf(startId) и система видит, что не осталось необработанных вызовов – сервис можно останавливать. Т.е. поступила куча вызовов, они все обработались и когда последний обработанный (но при этом не обязательно последний поступивший) выполняет stopSelf(startId) – сервис останавливается.
Но на самом деле алгоритм чуть другой. Сервис останавливается, когда последний полученный (а не последний обработанный) вызов выполняет метод stopSelf(startId). А при этом могут продолжать работать ранее полученные вызовы. Почему так сделано – я не знаю.
В общем, наверно сумбурно объяснил, сейчас на примерах все станет понятнее.
А метод stopSelfResult(startId) аналогичен методу stopSelf(startId), но при этом еще возвращает boolean значение – остановил он сервис или нет.
Project name: P0931_ServiceStop
Build Target: Android 2.3.3
Application name: ServiceStop
Package name: ru.startandroid.develop.p0931servicestop
Create Activity: MainActivity
Добавим в strings.xml строки:
Только кнопка для запуска сервиса.
Создаем сервис MyService.java:
Скажем прямо, тут немного нетривиально получилось 🙂 , особенно если опыт работы в Java небольшой. Но попробуем разобраться.
В onCreate создаем некий объект someRes. Это моя выдумка, на примере этого объекта я попробую показать, какую нехорошую ситуацию с ресурсами можно получить с применением метода stopSelf(startId). Этот объект будет использоваться сервисом в обработках вызовов. Пока что на него можно особо не смотреть.
Executors.newFixedThreadPool(1) – эта строка дает нам объект (я буду называть его — экзекьютор), который будет получать от нас задачи (Runnable) и запускать их по очереди в одном потоке (на вход ему мы передаем значение 1). Он сделает за нас всю работу по управлению потоками.
В onDestroy обнуляем someRes.
В onStartCommand мы читаем из intent параметр time. Создаем Runnable-объект MyRun, передаем ему time и startId и отдаем этот объект экзекьютору, который его запустит в отдельном потоке.
MyRun – Runnable-объект. Он и будет обрабатывать входящие вызовы сервиса. В конструкторе он получает time и startId. Параметр time будет использован для кол-ва секунд паузы (т.е. эмуляции работы). А startId будет использован в методе stopSelf(startId), который даст сервису понять, что вызов под номером strartId обработан. В лог выводим инфу о создании, старте и завершении работы. Также здесь используем объект someRes, в лог просто выводим его класс. Если же объект = null, то ловим эту ошибку и выводим ее в лог.
В общем, получилась, на первый взгляд, непонятная мегамонстроконструкция, но я реально не смог придумать ничего проще, чтобы наглядно показать тему урока. Сейчас все это взлетит и станет понятнее )
Почему вообще я использую потоки, я показал в прошлом уроке. Т.к. сервис работает в том же потоке, что и приложение и соответственно будет тормозить экран своей работой.
Да, и не забудьте прописать сервис в манифесте!
По нажатию на кнопку мы отправляем вызов в сервис три раза. И в intent помещаем параметр time.
Соответственно в сервисе будет три раза выполнен метод onStartCommand. Будет создано и передано экзекьютору три MyRun-объекта. Он их по очереди начнет выполнять. Это займет у него соответственно 7,2 и 4 секунд (время паузы мы передаем в intent-е). В конце обработки каждого MyRun будет выполняться stopSelf(startId).
Все сохраняем и запускаем приложение.
Жмем Start, открываем логи и ждем секунд 15. Все должно закончиться строкой MyService onDestroy
Давайте разбирать, чего получилось.
MyService onStartCommand
MyRun#1 create
MyService onStartCommand
MyRun#2 create
MyService onStartCommand
MyRun#3 create
Три раза выполнился метод onStartCommand, т.к. мы в приложении три раза вызвали startService. В каждом вызове создалось по одному объекту MyRun. После символа # идет значение startId. Т.е. видим, что счетчик вызовов работает и startId увеличивается на единицу при каждом вызове.
Все MyRun объекты были переданы экзекьютору, и он начинает их обрабатывать по очереди в одном потоке.
MyRun#1 start, time = 7
MyRun#1 someRes = class java.lang.Object
MyRun#1 end, stopSelf(1)
Первый готов. Метод stopSelf(1) вызван, сервис продолжает жить.
MyRun#2 start, time = 2
MyRun#2 someRes = class java.lang.Object
MyRun#2 end, stopSelf(2)
Второй готов. Метод stopSelf(2) вызван, сервис продолжает жить.
MyRun#3 start, time = 4
MyRun#3 someRes = class java.lang.Object
MyRun#3 end, stopSelf(3)
MyService onDestroy
Третий готов. Метод stopSelf(3) вызван и сервис после этого остановлен (MyService onDestroy), т.к. для последнего поступившего вызова (номер 3 в нашем случае) был вызван stopSelf(startId).
Но, как я написал в начале урока, мне кажется странным останавливать сервис, если закончена обработка последнего поступившего вызова. В этом примере у нас вызовы обрабатывались по очереди и проблем не возникло. Т.е. последний поступивший вызов обрабатывался последним и его stopSelf(startId) останавливал сервис. Но, что если вызовы будут обрабатываться параллельно? И последний поступивший вызов выполнит stopSelf(startId), а первый поступивший еще будет работать? Проверим.
В MyService.java в методе onCreate в строке создания экзекьютора поменяйте 1 на 3. Должно получиться так:
Теперь наш экзекьютор будет выполнять поступающие ему задачи не в одном, а в трех разных потоках. Как говорил один полосатый кошак из Простоквашино: «я и так счастливый был, а теперь в три раза счастливее стал, потому что у меня теперь три потока есть» 🙂 Соответственно, три наших вызова будут теперь обработаны параллельно, а не по очереди. И пришло время обратить внимание на someRes.
Все сохраним и запустим, жмем Start. На этот раз все заняло не 15 сек, а 7. Последняя строка логов должна быть такой: MyRun#1 end, stopSelf(1)
Разбираемся в логах.
MyService onStartCommand
MyRun#1 create
MyService onStartCommand
MyRun#2 create
MyRun#1 start, time = 7
MyService onStartCommand
MyRun#3 create
MyRun#2 start, time = 2
MyRun#3 start, time = 4
(у вас может быть немного иной порядок строк)
Три раза выполнился метод onStartCommand, т.к. мы в приложении три раза вызвали startService. В каждом вызове создалось по одному объекту MyRun и все они сразу начали работать, потому что экзекьютор теперь раскидал их по трем потокам и им не надо ждать друг друга.
Судя по параметру time, который мы используем для паузы, MyRun#2 закончит работать первым (через 2 сек.), MyRun#3 – вторым (через 4 сек.), MyRun#1 – третьим (через 7 сек.). Так и происходит.
MyRun#2 someRes = class java.lang.Object
MyRun#2 end, stopSelf(2)
Объект someRes доступен. Вызов с startId = 2 обработан. stopSelf(2) вызван – сервис продолжает жить.
MyRun#3 someRes = class java.lang.Object
MyRun#3 end, stopSelf(3)
MyService onDestroy
someRes доступен. Вызов с startId = 3 обработан. stopSelf(3) вызван – сервис остановлен (MyService onDestroy). Тут все верно — последний поступивший вызов имеет startId = 3, следовательно, вызов метода stopSelf(3) останавливает сервис. Следовательно, выполнился метод onDestroy, а в нем обнулился someRes.
MyRun#1 error, null pointer
MyRun#1 end, stopSelf(1)
someRes недоступен, т.к. он был обнулен чуть раньше в onDestroy. Ну и вызов метода stopSelf(1) уже бесполезен. Сервис был официально остановлен ранее.
Т.е. получилась неприятная ситуация, когда мы в onDestroy освободили объект, а он был еще нужен. А ведь вместо someRes мог быть объект по работе с БД. Здесь надо быть аккуратным, понимать механизм работы stopSelf(startId) и, когда именно этот метод остановит сервис.
Ну и напоследок рассмотрим метод stopSelfResult(startId). Напомню, что он полностью аналогичен методу stopSelf(startId), и при этом возвращает boolean-значение, остановлен сервис или нет после вызова этого метода.
В MyService.java в классе MyRun перепишем метод stop:
Мы выводим в лог результат вызова метода stopSelfResult.
Сохраняем, запускаем и жмем Start.
MyService onCreate
MyService onStartCommand
MyRun#1 create
MyService onStartCommand
MyRun#2 create
MyRun#1 start, time = 7
MyService onStartCommand
MyRun#3 create
MyRun#2 start, time = 2
MyRun#3 start, time = 4
MyRun#2 someRes = class java.lang.Object
MyRun#2 end, stopSelfResult(2) = false
MyRun#3 someRes = class java.lang.Object
MyService onDestroy
MyRun#3 end, stopSelfResult(3) = true
MyRun#1 error, null pointer
MyRun#1 end, stopSelfResult(1) = false
Видим, что stopSelfResult(3) вернул true, и тем самым сообщил нам, что именно он остановил сервис. А stopSelfResult(1) и stopSelfResult(2) вернули false – их вызов не привел к остановке сервиса.
Понимаю, что сложно это все, но надеюсь, что у меня получилось тему раскрыть. Если остаются сомнения, попробуйте поиграться экзекьютором, кол-вом потоков и вызовов, и параметром time – должно стать понятнее.
А вообще, до тех пор, пока вам это все не понадобится в боевых условиях, вполне можно понимать это не до конца.
На следующем уроке:
— рассмотрим подробнее метод onStartCommand
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Источник
Служба (Service)
Службы (Сервисы) в Android работают как фоновые процессы и представлены классом android.app.Service. Они не имеют пользовательского интерфейса и нужны в тех случаях, когда не требуется вмешательства пользователя. Сервисы работают в фоновом режиме, выполняя сетевые запросы к веб-серверу, обрабатывая информацию, запуская уведомления и т.д. Служба может быть запущена и будет продолжать работать до тех пор, пока кто-нибудь не остановит её или пока она не остановит себя сама. Сервисы предназначены для длительного существования, в отличие от активностей. Они могут работать, постоянно перезапускаясь, выполняя постоянные задачи или выполняя задачи, требующие много времени.
Клиентские приложения устанавливают подключение к службам и используют это подключение для взаимодействия со службой. С одной и той же службой могут связываться множество клиентских приложений.
Android даёт службам более высокий приоритет, чем бездействующим активностям, поэтому вероятность того, что они будут завершены из-за нехватки ресурсов, заметно уменьшается. По сути, если система должна преждевременно завершить работу запущенного сервиса, он может быть настроен таким образом, чтобы запускаться повторно, как только станет доступно достаточное количество ресурсов. В крайних случаях прекращение работы сервиса (например, задержка при проигрывании музыки) будет заметно влиять на впечатления пользователя от приложения, и в подобных ситуациях приоритет сервиса может быть повышен до уровня активности, работающей на переднем плане.
Используя сервис, можете быть уверены, что ваши приложения продолжат работать и реагировать на события, даже если они в неактивном состоянии. Для работы службам не нужен отдельный графический интерфейс, как в случае с активностями, но они по-прежнему выполняются в главном потоке хода приложения. Чтобы повысить отзывчивость вашего приложения, нужно уметь переносить трудоёмкие процессы (например, сетевые запросы) в фоновые потоки, используя классы Thread и AsyncTask.
Службы идеально подходят для проведения постоянных или регулярных операций, а также для обработки событий даже тогда, когда активности вашего приложения невидимы, работают в пассивном режиме или закрыты.
Сервисы запускаются, останавливаются и контролируются из различных компонентов приложения, включая другие сервисы, активности и приёмники широковещательных намерений. Если ваше приложение выполняет задачи, которые не зависят от прямого взаимодействия с пользователем, сервисы могут стать хорошим выбором.
Запущенные сервисы всегда имеют больший приоритет, чем бездействующие или невидимые активности, поэтому менее вероятно, что их работа завершится преждевременно при распределении ресурсов. Единственная причина, почему Android может досрочно остановить Сервис, — выделение дополнительных ресурсов для компонентов, работающих на переднем плане (как правило, для активностей). Если такое случится, ваш сервис автоматически перезапустится, когда будет достаточно доступных ресурсов.
Когда сервис напрямую взаимодействует с пользователем (например, проигрывая музыку), может понадобиться повысить его приоритет до уровня активностей, работающих на переднем плане. Это гарантия того, что сервис завершится только в крайнем случае, но при этом снижается его доступность во время выполнения, мешая управлять ресурсами, что может испортить общее впечатление от приложения.
Приложения, которые регулярно обновляются, но очень редко или нерегулярно взаимодействуют с пользователем, можно назвать первыми кандидатами на реализацию в виде сервисов. Проигрыватели MP3 и приложения, отслеживающие спортивные результаты, — примеры программ, которые должны постоянно работать и обновляться без необходимости отображать активность.
Создание службы
Чтобы определить службу, необходимо создать новый класс, расширяющий базовый класс Service. Можно воспользоваться готовым мастером создания класса для сервиса в Android Studio. Щёлкаем правой кнопкой мыши на папке java (или на имени пакета) и выбираем New | Service | Service:
В следующем окне выбираем имя сервиса (флажки оставляем) и нажимаем кнопку Finish.
При этом сервис автоматически зарегистрируется в манифесте в секции .
Если бы мы убрали флажки на экране мастера, то оба атрибута имели бы значение false. Например, атрибут exported даёт возможность другим приложениям получить доступ к вашему сервису.
Имеются и другие атрибуты, например, permission, чтобы сервис запускался только вашим приложением.
Также вы можете обойтись без мастера и создать вручную класс сервиса и запись в манифесте, теперь вы знаете, из чего он состоит.
Жизненный цикл служб
Подобно активностям служба имеет свои методы жизненного цикла:
Для быстрого создания заготовок нужных методов используйте команду меню Code | Override Methods. или набирайте сразу имя метода, используя автодополнение.
Реализуя эти методы обратного вызова в своей службе, вы можете контролировать жизненные циклы службы. В полном жизненном цикле службы существует два вложенных цикла:
- полная целая жизнь службы — промежуток между временем вызова метода onCreate() и временем возвращения onDestroy(). Подобно активности, для служб производят начальную инициализацию в onCreate() и освобождают все остающиеся ресурсы в onDestroy()
- активная целая жизнь службы — начинается с вызова метода onStartCommand(). Этому методу передаётся объект Intent, который передавали в метод startService().
Из своего приложения службу можно запустить вызовом метода Context.startService(), остановить через Context.stopService(). Служба может остановить сама себя, вызывая методы Service.stopSelf() или Service.stopSelfResult().
Можно установить подключение к работающей службе и использовать это подключение для взаимодействия со службой. Подключение устанавливают вызовом метода Context.bindService() и закрывают вызовом Context.unbindService(). Если служба уже была остановлена, вызов метода bindService() может её запустить.
Методы onCreate() и onDestroy() вызываются для всех служб независимо от того, запускаются ли они через Context.startService() или Context.bindService().
Если служба разрешает другим приложениям связываться с собой, то привязка осуществляется с помощью дополнительных методов обратного вызова:
- IBinder onBind(Intent intent)
- onUnbind(Intent intent)
- onRebind(Intent intent)
В метод обратного вызова onBind() передают объект Intent, который был параметром в методе bindService(), а в метод обратного вызова onUnbind() — объект Intent, который передавали в метод unbindService(). Если служба разрешает связывание, метод onBind() возвращает канал связи, который используют клиенты, чтобы взаимодействовать со службой. Метод обратного вызова onRebind() может быть вызван после onUnbind(), если новый клиент соединяется со службой.
Запуск сервиса и управление его перезагрузкой
В большинстве случаев также необходимо переопределить метод onStartCommand(). Он вызывается каждый раз, когда сервис стартует с помощью метода startService(), поэтому может быть выполнен несколько раз на протяжении работы. Вы должны убедиться, что ваш сервис это предусматривает.
Метод onStartCommand() заменяет устаревший метод onStart(), который использовался в Android 2.0. В отличие от onStart() новый метод позволяет указать системе, каким образом обрабатывать перезапуски, если сервис остановлен системой без явного вызова методов stopService() или stopSelf().
Службы запускаются в главном потоке приложения; это значит, что любые операции, выполняющиеся в обработчике onStartCommand(), будут работать в контексте главного потока GUI. На практике при реализации сервиса в методе onStartCommand() создают и запускают новый поток, чтобы выполнять операции в фоновом режиме и останавливать сервис, когда работа завершена.
Такой подход позволяет методу onStartCommand() быстро завершить работу и даёт возможность контролировать поведение сервиса при его повторном запуске, используя одну из констант.
- START_STICKY — Описывает стандартное поведение. Похоже на то, как был реализован метод onStart() в Android 2.0. Если вы вернёте это значение, обработчик onStartCommand() будет вызываться при повторном запуске сервиса после преждевременного завершения работы. Обратите внимание, что аргумент Intent, передаваемый в onStartCommand(), получит значение null. Данный режим обычно используется для служб, которые сами обрабатывают свои состояния, явно стартуя и завершая свою работу при необходимости (с помощью методов startService() и stopService()). Это относится к службам, которые проигрывают музыку или выполняют другие задачи в фоновом режиме
- START_NOT_STICKY — Этот режим используется в сервисах, которые запускаются для выполнения конкретных действий или команд. Как правило, такие службы используют stopSelf() для прекращения работы, как только команда выполнена. После преждевременного прекращения работы службы, работающие в данном режиме, повторно запускаются только в том случае, если получат вызовы. Если с момента завершения работы Сервиса не был запущен метод startService(), он остановится без вызова обработчика onStartCommand(). Данный режим идеально подходит для сервисов, которые обрабатывают конкретные запросы, особенно это касается регулярного выполнения заданных действий (например, обновления или сетевые запросы). Вместо того, чтобы перезапускать сервис при нехватке ресурсов, часто более целесообразно позволить ему остановиться и повторить попытку запуска по прошествии запланированного интервала
- START_REDELIVER_INTENT — В некоторых случаях нужно убедиться, что команды, которые вы посылаете сервису, выполнены. Этот режим — комбинация предыдущих двух. Если система преждевременно завершила работу сервиса, он запустится повторно, но только когда будет сделан явный запрос на запуск или если процесс завершился до вызова метода stopSelf(). В последнем случае вызовется обработчик onStartCommand(), он получит первоначальное намерение, обработка которого не завершилась должным образом.
Обратите внимание, что при окончании всех операций каждый из этих режимов требует явной остановки сервиса с помощью методов stopService() или stopSelf().
Режим перезапуска, который вы указываете в качестве значения, возвращаемого методом onStartCommand(), будет влиять на параметры, передаваемые при последующих вызовах.
Изначально намерение выступает в качестве параметра, который передастся в метод startService() при запуске сервиса. После перезапуска системой он может иметь значение null (если установлен режим START_STICKY) или оригинальное (если установлен флаг START_REDELIVER_INTENT).
Параметр flag может помочь узнать, как именно был запущен сервис:
- START_FLAG_REDELIVERY — указывает на то, что параметр Intent повторно передан при принудительном завершении работы сервиса перед явным вызовом метода stopSelf()
- START_FLAG_RETRY — указывает на то, что сервис повторно запущен после непредвиденного завершения работы; передается в том случае, если ранее сервис работал в режиме START_STICKY
Запуск и остановка служб
Чтобы запустить службу, в клиентском приложении необходимо вызывать метод startService(). Существует два способа вызова службы:
Пример для явного вызова службы с именем MyService:
Также можно явно определить службу, создав экземпляр класса этой службы.
Пример неявного вызова службы:
Чтобы использовать этот пример, необходимо включить константу SERVICE_ACTION, идентифицирующую службу, в класс MyService, например:
Используйте фильтр намерений, чтобы зарегистрировать его как провайдера SERVICE_ACTION. Если служба потребует разрешений, которые не имеет ваше приложение, то запрос вызовет исключение SecurityException.
Как только сервис завершил выполнение тех действий, для которых он запускался, вы должны вызвать метод stopSelf() либо без передачи параметра, чтобы ускорить остановку работы, либо передав значение startId, чтобы убедиться, что задачи выполнены для всех экземпляров, запущенных с помощью вызова startService(), как показано в следующем фрагменте:
Явная остановка сервиса по завершении необходимых задач позволяет системе получать обратно ресурсы, которые в ином случае оставались бы заняты. Поскольку приоритет сервисов повышенный, система, как правило, не завершает их работу, поэтому её окончание по собственной инициативе может существенно улучшить эффективность использования ресурсов вашим приложением.
Для остановки работы используйте метод stopService(), передавая ему объект Intent, определяющий нужный сервис.
Если метод startService() вызывается для сервиса, который уже работает, обработчик onStartCommand(), принадлежащий объекту Service, будет вызван повторно. Вызовы startService() не накапливаются, поэтому единственный вызов метода stopService() завершит работу сервиса, неважно, сколько раз производился вызов startService().
Давайте создадим практическое приложение для работы со службой. Наша служба будет запускать на воспроизведение музыкальный файл, который будет проигрываться в фоновом режиме. Управлять службой можно будет из активности. Создайте новый проект. Для службы создайте отдельный класс PlayService. Служба будет загружать музыкальный файл sample.mp3 из каталога res/raw/ (разместите там свой MP3-файл).
PlayService.java
Зарегистрируем службу в файле манифеста.
В файле разметки для активности определим две кнопки: Старт и Стоп:
В классе активности в обработчиках событий кнопок будем вызывать методы startService() и stopService() для управления службой.
Запущенная служба будет выполняться независимо от состояния активности, несмотря на то, что эти компоненты находятся в одном приложении: если её завершить, служба все равно останется работать.
Если вы хотите, чтобы сервис запускался и после перезагрузки устройства, то следует создать приёмник широковещательных сообщений и запустить в нём сервис.
Приёмник регистрируется в манифесте с именем действия BOOT_COMPLETED:
Пример для Kotlin
Класс для службы, которая будет генерировать случайные числа через определённый промежуток времени. Не забудьте прописать службу в манифесте.
Разместите на экране активности три кнопки: запуск, остановка и статус службы. Код для активности.
Список всех запущенных сервисов
Ущемление прав службы
Google последовательно борется с ограничениями для служб, урезая их возможности. Делается это для того, чтобы службы не висели в памяти бесконечно долго и тратили заряд батареи. Ограничение возможностей происходит постепенно от версии к версии. В последних версиях уже можно столкнуться с примерами, когда выкидывается исключение при неправильной работе с службами.
Для решения проблем следует изучить такие вещи как JobScheduler, Firebase Job Dispatcher, WorkManager. Также появилось понятие Foreground service.
Системные службы
Кроме создания собственных сервисов, вы можете использовать системные сервисы. Вот небольшой список:
- Account Service — служба для управления пользовательскими учётными записями
- Activity Service — служба для управления активностями
- Alarm Service — служба для отправки разовых или периодических оповещений в заданное время
- Bluetooth Service — служба для Bluetooth
- Clipboard Service — служба для управления буфером обмена
- Connectivity Service — служба для управления сетевыми соединениями
- Download Service — служба для управления загрузками
- Input Method Service — служба для управления текстовым вводом
- JobScheduler — служба для планирования задач
- Location Service — служба для отслеживания координат
- Layout Inflater Service — служба для управления компоновкой экрана при динамическом создании из кода
- NFC Service — служба для управления NFC
- Notification Service — служба для управления уведомлениями
- Power Service — служба для управления энергопотреблением
- Search Service — служба для управления глобальным поиском
- Sensor Service — служба для доступа к датчикам
- Telephony Service — служба для управления телефонными функциями
- Vibrator Service — служба для доступа к виброзвонку
- Wallpaper Service — служба для управления обоями на домашнем экране
- Wifi Service — служба для управления соединениями Wi-Fi
Источник