Что такое и зачем нужен Service? Какие бывают виды сервисов?
Service – это компонент приложения, который используется для выполнения долгих фоновых операций без взаимодействия с пользователем.
Любой компонент приложения может запустить сервис, который продолжит работу, даже если пользователь перейдет в другое приложение.
Примеры использования сервисов: проигрывание музыки, трекинг локации водителя в приложении такси, загрузка файла из сети.
Сервисы делятся на два вида по способу использования: Started и Bound, и на два вида по способу взаимодействия с пользователем: Background и Foreground.
Когда спрашивают о видах сервисов обычно имеют в виду способ использования.
Started Service Запускается методом startService(Intent intent). Intent должен быть явным (explicit), это значит, что при создании объекта Intent было передано имя класса сервиса.
После запуска сервиса вызывается метод onStartCommand().
Остановить сервис можно вызовом метода stopSelf() из самого сервиса или методом stopService() из другого компонента.
Bound Service привязывается к компоненту вызовом метода bindService(Intent service, ServiceConnection serviceConnection, int flags).
Аргумент serviceConnection используется для взаимодействия с привязанным сервисом. Сервис стартует после вызова bindService() , если аргумент flags имеет значение BIND_AUTO_CREATE.
После вызова bindService() у сервиса вызывается метод onBind().
Для отвязывания компонента от сервиса используется метод unbindService(). У сервиса вызывается метод onUnbind().
Если у сервиса больше нет привязанных компонентов, вызывается метод onDestroy().
Компонент может быть привязан к сервису, запущенному методом startService() . В этом случае сервис относится сразу и к Started и к Bound.
Bound и Started сервисы важно различать, потому что у них разные жизненные циклы.
Сервисы
Сервис (обычно в русской литературе применяется термин служба, но мы будем использовать слово сервис из-за созвучности с именем класса) это объект типа Service, который может выполнять длительные операции в фоновом режиме и который не предоставляет пользовательский интерфейс. Другие компоненты приложения могут запустить сервис и он будет работать в фоновом режиме, даже если пользователь переключится в другое приложение. К тому же, компонент может быть связан с сервисом и даже выполнять межпроцессное взаимодействие с ним. Например, сервис может выполнять загрузку по сети, проигрывать музыкальный файл, записывать или читать из файла или взаимодействовать с поставщиками содержимого, и все это в фоновом режиме.
Сервис может находиться в двух состояниях:
Запущен Сервис “запущен”, если компонент приложения запустил его с помощью метода startService(). После запуска сервис бесконечно работает в фоновом режиме, даже если запустивший его компонент уже уничтожен. Обычно запущенный сервис выполняет одну операцию и не возвращает результат. Например, это может быть скачивание файла по сети. Когда операция заканчивается, сервис должен сам себя остановить. Связан Сервис “связан”, если компонент вызвал метод bindService(). Связанный сервис предлагает клиент-серверный интерфейс, позволяющий компонентам взаимодействовать с ним, отправлять запросы, получать результат, и даже выполнять межпроцессное взаимодействие (IPC). Связанный сервис работает до тех пор, пока другой компонент приложения с ним связан. С сервисом может быть связано несколько компонентов, и как только последний из них разрывает связь, сервис уничтожается.
Хотя в этом документе оба типа сервисов обсуждаются отдельно, ваши сервисы могут работать в любом режиме – они могут быть запущены или связаны. Все зависит от того, как вы реализуете пару методов обратного вызова onStartCommand() для разрешения запуска и onBind() для разрешения связывания.
Независимо от того, запущено приложение, связано или и то и другое вместе, любой компонент может использовать сервис (даже компонент другого приложения), также, как любой компонент может использовать явления – запустив его с помощью намерения Intent. Однако, вы можете объявить частный сервис в манифесте и заблокировать доступ к нему из других приложений. Это мы обсудим ниже.
Внимание: сервисы запускаются в основном потоке процесса – сервис не создает его собственный поток и не запускается в отдельном процессе (если не указано иное). Это означает, что если ваш сервис загружает процессор или блокирует операции (например проигрывает mp3), вы должны создавать для него отдельный поток. Таким образом вы предотвратите потенциальную ошибку Приложение не отвечает (ANR) и пользователь все еще сможет взаимодействовать с приложением в его основном потоке.
Основы
Когда использовать сервисы и потоки?
Сервис это простой компонент, который может работать в фоновом режиме даже если пользователь не взаимодействует с приложением. Поэтому создавайте сервис, только если он вам нужен.
Если вам необходимо выполнять работу за пределами основного потока, но только когда пользователь взаимодействует с приложением – используйте еще один поток, но не создавайте сервис. Например, если вам нужно проиграть музыку, но только пока явление запущено, вы можете создать поток в методе onCreate() , запустить его выполнение в методе onStart() и остановить в методе onStop() . Также подумать об использовании AsyncTask или HandlerThread.
Помните, что сервис по умолчанию работает в основном потоке приложения, поэтому создавайте для него отдельный поток, если в нем выполняется интенсивная работа с процессором или он блокирует операции.
Для создания сервиса необходимо создать подкласс Service. В нем необходимо переопределить некоторые методы обратного вызова, которые связаны с его жизненным циклом и предоставляют компонентам механизм связывания. Вот наиболее важные методы, которые необходимо реализовать:
onStartCommand() Система вызывает этот метод, когда другой компонент, вроде явления, запрашивает запуск сервиса с помощью метода startService(). После выполнения метода сервис запускается и бесконечно работает в фоновом режиме. Если вы реализовали данный метод, позаботьтесь об остановке сервиса после выполнения его работы, вызвав метод stopSelf() или stopService() (Если вы собираетесь предоставлять только связывание, вам не нужно реализовывать данный метод). onBind() Система вызывает данный метод, когда другой компонент хочет установить связь с сервисом и вызывает метод bindService(). В вашей реализации метода необходимо предоставить интерфейс, который будет использовать клиент для взаимодействия с сервисом. Для этого метод должен вернуть объект типа IBinder. Этот метод всегда должен быть реализован, но в случае, если сервис не разрешает связывание, метод должен возвращать null. onCreate() Система вызывает этот метод при создании сервиса для выполнения первоначальных настроек (до вызова onStartCommand() или onBind()). Если сервис уже запущен, данный метод не вызывается. onDestroy() Метод вызывается когда сервис долгое время не используется и должен быть уничтожен. Сервис должен реализовывать данный метод для освобождения ресурсов, вроде потоков, зарегистрированных слушателей, приемников и.т.п. Этот метод вызывается самым последним перед уничтожением сервиса.
Если компонент запускает сервис с помощью метода startService(), сервис продолжает работать, пока не остановит сам себя или пока его не остановит другой компонент с помощью метода stopService().
Если компонент создает сервис с помощью метода bindService(), сервис будет запущен, пока компонент с ним связан.
Система Android принудительно останавливает сервис только когда заканчивается память и ее необходимо освободить для явления, которое получило пользовательский фокус. Если сервис связан с явлением, получившим фокус, то маловероятно, что он будет остановлен, а если сервис объявлен для работы на переднем плане (обсуждается ниже), он практически никогда не будет остановлен. Если же сервис выполняется уже длительное время, система понижает его позицию в списке фоновых задач и он будет первым кандидатом на отключение. Поэтому не забывайте должным образом обрабатывать перезапуск вашего сервиса системой. Если система уничтожила сервис, он перезапускается как только появятся свободные ресурсы (хотя это также зависит от значения, которое возвращает метод onStartCommand(), но об этом поговорим позже). Подробная информация об уничтожении сервисов системой содержится в разделе Процессы и потоки.
В следующих разделах мы покажем как создавать сервисы различных типов и как взаимодействовать с ними их других компонентов приложения.
Объявление сервиса в манифесте
Аналогично явлениям и другим компонентам, вы должны объявить все сервисы приложения в файле манифеста. Для этого добавьте дочерний элемент <service> в <application>, например:
Погружение в службы Android

Перевод статьи «Deep Dive into Android Services» от Nazmul Idris. Я оставил оригинальное название автора, хотя это скорее не «погружение», а «знакомство». Думаю, текст будет полезен начинающим разработчикам. Статья отлично дополняет офф. документацию по службам на Android. В статье разбираются особенности взаимодействия с запущенными и привязанными службами. Плюс статьи в том, что учитываются изменения в работе со службами в Android O. В переводе есть незначительные, по сравнению с оригиналом, изменения, добавленные для пущей ясности.
Введение
Большинство современных android-приложений выполняют часть задач в фоне. Это означает, что задачи выполняются в фоновом потоке, а не в потоке пользовательского интерфейса (UI-поток).
Если вы создаете Thread (поток) или Executor (обертка управления потоками) в конкретной Activity своего приложения, то это может привести к непредсказуемым результатам. Например, во время простой смены ориентации экрана, ваша Activity создается заново и потокам, привязанным к старой Activity , некуда возвращать результат.
Чтобы справиться с этим вы могли бы использовать AsyncTask . Но что, если вашему приложению необходимо запустить этот фоновый поток не только из Activity , но и из нотификации (notification) или из другого компонента?
В этом случае служба (service) это подходящий компонент Android, который свяжет жизненный цикл потока со своим жизненным циклом, и таким образом не потеряет его.
Служба — это компонент android-приложения без видимого интерфейса, который запускается в основном потоке приложения. Служба должна быть объявлена в манифесте. Если вам необходимо чтобы служба работала в фоновом потоке, вы должны самостоятельно реализовать это.
Термины фон и передний план перегружены, и могут применяться к:
- жизненному циклу компонентов Android
- потокам
В этой статье, по умолчанию будем считать, что термины фон и передний план относятся к жизненному циклу. Но, когда будет идти речь о потоках, мы будем явно говорить фоновый поток или поток переднего плана.
Существует подкласс android-служб, называемый IntentService , который запускает задачи в фоновом потоке «из коробки». Но мы не будем говорить о таких службах в этой статье.
Потоки, службы и жизненный цикл компонентов Android
Давайте сделаем шаг назад и посмотрим на более общую картину того, что должны делать службы. Ваш код, который работает в фоновом потоке, например Thread или Executor , на самом деле не связан с жизненным циклом какого-либо компонента Android. Если мы говорим об Activity , то она имеет конкретную точку запуска и остановки работы, основываясь на взаимодействии с пользователем. Однако эти точки начала и конца работы Activity не обязательно связаны с жизненным циклом Thread или Executor .

Ниже приведены пояснения к основным временным моментам этой диаграммы Гантта. Детали этих моментов (и пояснения к ним) приведены в остальной части статьи.
Метод службы onCreate() вызывается в момент ее создания (путем запуска или привязки к ней).
Затем, через некоторое время, служба запускает Thread или Executor . Когда Thread завершает работу, он дает об этом знать службе, чтобы та могла вызвать метод stopSelf() . Это довольно распространенный шаблон реализации службы.
Код, который вы пишите в ваших Thread или Executor , должен сообщить службе о запуске или остановке фонового потока.
- Когда поток начинает работу, он должен установить начальное состояние сервиса путем вызова startService()
- Когда поток завершает работу, он должен вызвать stopSelf() у службы.
Метод службы onDestroy() вызывается системой только когда вы сообщили службе, что пришло время завершать работу. Служба не знает, что будет происходить в коде ваших Thread или Executor — это зона вашей ответственности. Таким образом, задача программиста сообщить службе о начале и о завершении работы.
Службы делятся на два вида: запущенные и привязанные. Кроме того, служба может быть запущенной и допускать привязку. Мы рассмотрим каждый из случаев:
- Запущенная служба
- Привязанная служба
- Привязанная и запущенная служба одновременно
Изменения в Android O
В Android O (API 26) произошли существенные изменения в регулировании фоновых служб системой. Одно из главных изменений в том, что запущенная служба, которая не в белом списке (в белый список помещаются службы, работа которых видна пользователю; подробнее смотри в офф. документации) или которая явно не сообщает пользователю о своей работе, не будет запускаться в фоновом потоке после закрытия Activity . Другими словами, вы должны создать уведомление (notification), к которому вы прикрепляете запущенную службу. И вы должны запускать службу с помощью нового метода startForegroundService() (а не с помощью startService() ). И, после создания службы, у вас есть пять секунд чтобы вызвать метод startForeground() запущенной службы и показать видимое пользователю уведомление. Иначе система останавливает службу и показывает ANR («приложение не отвечает»). Ниже мы разъясняем эти положения с помощью примеров кода.
Запущенные службы
Запущенные службы начинают свою работу после вызова метода startService(Intent) в вашей Activity или службе. При этом Intent должен быть явным. Это означает, что вы должны явно указать в Intent имя класса запускаемой вами службы. Или, если вам важно допустить некоторую неопределенность в отношении того, какая служба запускается, вы можете предоставить фильтры намерений для ваших служб и исключить имя компонента из Intent, но затем вы должны установить пакет для намерения с помощью setPackage() , который обеспечивает достаточное устранение неоднозначности для целевой службы. Ниже мы приводим пример создания явного Intent :
Чтобы служба стала запущенной, вы должны вызвать startService() с явным намерением. Если вы не сделаете этого, тогда служба не перейдет в запущенное состояние. И, таким образом, она не сможет перейти на передний план, и stopSelf() на самом деле ничего не выполнит.
Итак, если вы не перевели службу в запущенное состояние, вы не сможете прикрепить ее к уведомлению. Это довольно важные вещи, о которых вы должны помнить, когда вам нужно перевести службу в запущенное состояние.
Служба может быть запущена несколько раз. Каждый раз, когда она запускается, вызывается onStartCommand() . Этому методу передается несколько параметров наряду с явным Intent . Даже если вы запускаете службу несколько раз, она вызывает onCreate() только однажды (конечно, если до этого служба уже не была привязана). Чтобы завершить работу, служба должна вызвать stopSelf() . После того, как служба будет остановлена (когда вы остановите ее), и если с ней ничего больше не связано, вызывается onDestroy() . Помните об этом, когда выделяете ресурсы для вашей запущенной службы.
Intent
Для старта запущенной службы необходим Intent . Компонент Android, в котором стартует служба, на самом деле не хранит соединение с ней, и если ему необходимо что-то сообщить запущенной службе, он может запустить ее снова, используя другой Intent . Это главная разница между запущенной и привязанной службой. Привязанные службы со своей стороны реализуют шаблон клиент-сервер. Где клиент (компонент Android UI или другая служба) хранит соединение и может через него вызывать методы непосредственно у службы.
Помните, что в Android O многое изменилось в отношении запущенных служб. Они больше не могут работать достаточно долго в фоне без механизма постоянного уведомления. И метод старта запущенной службы в фоне в Android O — это startForegroundService(Intent) .
Передний план и механизм постоянного уведомления
Запущенная служба может работать на переднем плане. Опять же, термин передний план не относится к тому работает ли служба в фоновом потоке или в главном потоке. Но это означает, что система присвоит службе наивысший приоритет, и поэтому служба не является кандидатом для удаления системой в случае нехватки памяти. Помещать службу на передний план стоит только в том случае, когда это действительно необходимо для создания современного и отзывчивого приложения.
Примеры использования службами переднего плана:
- Приложения, которые проигрывают медиа-файлы в фоне.
- Приложения, которые обновляют данные о местоположении в фоне.
Когда запущенная служба помещается на передний план, она должна вывести на экран уведомление, явно сообщая пользователю, что служба работает. Это важно, потому что запущенная служба на переднем плане отделена от жизненного цикла UI-компонентов (за исключением, разумеется, самого постоянного уведомления). И нет другого способа сообщить пользователю о том, что на его телефоне что-то работает (и потенциально потребляет много ресурсов) кроме как вывести в UI постоянное уведомление.
Ниже пример старта запущенной службы на переднем плане:
Вот код создания постоянного уведомления в версиях
Кроме того, вот еще одна статья, в которой больше деталей о создании уведомлений в MediaStyle (поскольку для фонового проигрывания аудио-файлов нужны как уведомления, так и привязанные и запущенные службы)
Остановка запущенных служб
Обратите внимание, что параметр piStopService типа PendingIntent (который передается в конструктор уведомления) фактически передает Intent с константой Command.STOP типа Integer . Помните, что startService(Intent) может вызываться несколько раз? Это пример такого поведения. Чтобы остановить службу мы запускаем Intent через startService(Intent) и далее обрабатываем этот Intent в методе onStartCommand() запущенной службы.
Это объясняет почему метод onStartCommand() должен уметь обрабатывать Intent ы. Используя этот механизм мы можем «сказать» службе, чтобы она остановила работу. Ниже код, который иллюстрирует эти возможности:
Если вы хотите завершить выполнение запущенной службы на переднем плане, вы должны вызвать stopForeground(true) . Этот метод также завершит работу постоянного уведомления. Однако, саму службу это не остановит. Для этого следует вызвать stopSelf() .
Чтобы остановить службу вы можете выполнить одно из следующих действий:
- Как было показано выше, передайте Intent с дополнительным параметром в startService() , который затем будет обработан в onStartCommand() и фактически служба вызовет stopSelf() . И, если к службе не привязаны никакие другие компоненты, это вызовет onDestroy() и служба завершит свою работу.
- Вы также можете создать явный Intent (указывая на класс службы) и передать его в метод stopService() , который вызовет stopSelf() и, затем, onDestroy() аналогично п.1.
Вот несколько примеров остановки службы из Activity :
И вот код в вашей службе, который будет обрабатывать эти запросы (при условии, что ваша запущенная служба находится на переднем плане):
Привязанные службы
В отличие от запущенных служб, привязанные службы позволяют установить соединение между компонентом Android, привязанным к службе, и службой. Это соединение предоставляется реализацией интерфейса IBinder , который определяет методы для взаимодействия со службой. Простым примером этого может быть реализация привязанной службы в одном процессе с клиентом (т.е. в рамках вашего собственного приложения). В этом случае Java-объект, подкласс Binder , передается клиенту, который может использовать его для вызова методов службы.
В более сложных сценариях, когда необходимо, чтобы интерфейс службы был доступен для разных процессов, для предоставления клиенту интерфейса службы следует воспользоваться объектом Messenger (является ссылкой на объект Handler , который получает обратный вызов для каждого вызова от клиента), благодаря чему со службой можно взаимодействовать с помощью объектов Message . Объект Messenger фактически основан на AIDL (Android Interface Definition Language). Messenger создает очередь из всех запросов клиентов в рамках одного потока, поэтому служба одновременно получает только один запрос. Если необходимо, чтобы служба обрабатывала одновременно сразу несколько запросов, можно использовать AIDL напрямую.
Отличия между привязанной и запущенной службами:
- У клиентского компонента нет соединения с запущенной службой. Он просто использует объекты Intent посредством startService() или stopService() , которые обрабатываются службой в методе onStartCommand() .
- Когда клиентский компонент ( Activity , Fragment или другая служба) соединяются с привязанной службой, они получают реализацию IBinder , посредством которой они могут вызывать методы у привязанной службы.
В любом случае, когда службе (привязанной или запущенной) необходимо отправлять сообщения привязанному клиенту, ей следует использовать что-то вроде LocalBroadcastManager (в том случае, если клиент и служба работают в одном процессе). Привязанные службы обычно не подключаются к привязанному клиентскому компоненту напрямую.
bindService() и onCreate()
Для того, чтобы клиентский компонент стал привязанным к службе, необходимо вызвать bindService() с явным Intent , как и в случае с запущенной службой.
BIND_AUTO_CREATE это наиболее часто встречающийся флаг в случае вызова bindService() . Существуют и другие флаги (например, BIND_DEBUG_UNBIND или BIND_NOT_FOREGROUND ). В случае BIND_AUTO_CREATE у привязанной службы вызывается onCreate() , если служба до этого еще не была создана. Фактически это означает, что служба создается в момент первой привязки к ней.
Как только вызывается bindService() , службе необходимо реагировать на запрос клиента и предоставить ему экземпляр IBinder , посредством которого клиент сможет вызывать методы привязанной службы. В примере выше, это реализуется с помощью ссылки mServiceConnection . Это обратный вызов (callback) ServiceConnection , который привязанная служба будет использовать для уведомления клиента о завершении привязки. Он также позволит клиенту узнать о разрыве соединения со службой.
Другими словами, привязка выполняется асинхронно. bindService() возвращается сразу же и не возвращает клиенту объект IBinder . Для получения объекта IBinder клиенту необходимо создать экземпляр ServiceConnection и передать его в метод bindService() . Интерфейс ServiceConnection включает метод обратного вызова, который система использует для того, чтобы выдать объект IBinder .
Ниже приведен пример реализации ServiceConnection :
Привязка службы
Давайте посмотрим, что происходит на стороне привязанной службы, когда клиент вызывает bindService(Intent) .
В привязанной службе вы должны реализовать метод onBind() , для получения клиентом экземпляра IBinder . Метод ‘onBind()’ будет вызван только один раз, при первой привязке клиента. Для последующих клиентов, система выдаст такой же экземпляр IBinder :
Объект IBinder обеспечивает программный интерфейс, с помощью которого клиенты могут взаимодействовать со службой. Как говорилось выше, самый простой способ реализации IBinder — это расширение класса Binder , экземпляр которого возвращается из метода onBind() :
В примере выше, мы просто используем метод getService() , который просто возвращает Java-объект привязанной службы клиентскому компоненту. Ссылаясь на этот экземпляр IBinder , клиент может вызывать публичные методы у привязанной службы напрямую. Обратите внимание, что эти методы выполняются в клиентском потоке. И в случае Activity или Fragment эти методы будут выполняться в главном потоке. Поэтому стоит быть осторожным с методами в привязанной службе, которые могут блокировать поток или могут стать причиной ANR.
Отвязка от службы и вызов onDestroy()
Чтобы отвязаться от привязанной службы, клиент просто вызывает unbindService(mServiceConnection) . Затем система вызовет onUnbind() в самой службе. И, если у привязанной службы больше нет клиентов, и также, если, служба не является запущенной службой, то система вызывает onDestroy .
Вот как выглядит вызов unbindService() в клиентском компоненте:
В коде выше, метод onStop() в Activity переопределен для вызова unbindService() . В зависимости от требований UX к приложению ваш клиентский компонент может привязываться к службе и отвязываться от нее в методах onStart() и onStop() соответственно, или в любых других методах жизненного цикла клиентских компонентов на ваше усмотрение.
Вот пример как может выглядеть onUnbind() в коде привязанной службы:
Обычно вы вернете false . Но, если вернуть true , то при привязке следующего клиента к службе вместо onBind() будет вызван метод onRebind() .
Привязанные и запущенные службы одновременно
Бывают ситуации, когда вам могут пригодиться службы, которые являются запущенными и вместе с тем могут допускать привязку. В предыдущих разделах, мы показали особенности работы каждого из видов служб. И уже из этих особенностей можно понять, что создание привязанных и запущенных служб одновременно необходимо для реализации особого поведения в момент начала работы со службой и при завершении работы с ней.
Если служба не запущена, то клиент, который хочет привязаться к ней, вызовет onCreate() у службы. Если служба уже запущена, этот метод не вызывается. С другой стороны, если клиент отвязывается от службы и при этом служба не запущенная, то вызывается onDestroy() и служба уничтожается.
Вы можете запустить службу путем вызова метода startService(), вывести ее на передний план и показывать постоянное уведомление. Таким образом, вы реализуете все, что мы говорили о создании запущенных служб. Но кроме того, вы можете реализовать методы, которые позволят клиентам привязываться к службе, с помощью вызова метода bindService() . Особенность такой »двойной» службы в том, что даже при отвязке всех клиентов, служба продолжает свою работу и выполняется до тех пор, пока сама не остановит себя с помощью метода stopSelf() , или до тех пор, пока другой компонент не вызовет метод stopService() .
Переход в запущенное состояние
Поскольку клиент, привязываясь к службе, не переведет ее в запущенное состояние, то для привязанных и запущенных служб одновременно, требуется чтобы служба переходила в запущенное состояние самостоятельно. Вот, как можно это сделать с учетом Android O:
В коде под спойлером:
- Метод commandStart() может быть вызван клиентом, который привязывается к службе.
- Или commandStart() вызывается через методы startService() или startForegroundService() (для Android O).
Но, перед фактическим исполнением работы, служба сначала переводит себя в запущенное состояние.
Итак, когда клиент привязывается к службе, вызывается commandStart() . Служба еще не запущена. Давайте посмотрим на код, и увидим, что случится:
- Если служба привязывается к клиенту, то она не запущена (и в mServiceStarted содержится false )
- В этом случае вызывается moveToStarted() и там создается явный Intent с Extras Command.START , и далее вызывается startService() или startForegroundService() .
- Это приводит к вызову onStartCommand() , который опять вызывает commandStart() .
- Но теперь в commandStart() значение переменной mServiceIsStarted равняется true , и поэтому метод commandStart() выполняет свое прямое предназначение, т.е. запускает полезную работу службы.
Завершение работы службы и отвязывание
Если служба не в запущенном состоянии и клиентский компонент отвязывается от службы, то служба уничтожается и вызывается onDestroy()
Но если она в запущенном состоянии она не уничтожается. И она будет «убита», только если запущенное состояние будет остановлено (через вызов stopService(Intent) или вызов startService(Intent) c Extras в Intent , которые говорят о намерении остановить службу, например Command.STOP ).
Вот диаграмма, в которой суммируются состояния службы и переходы между ними для запущенной и привязанной службы одновременно:

Примеры
Реализацию большинства из того, о чем говорилось в статье, можно глянуть на GitHub.
Это небольшая утилита для Android O и N, которая держит телефон в активном состоянии, если он на зарядке.
Android. Собеседование #10. Services
Автор: ivanessence
1. Какой жизненный цикл у Service?
– onCreate()
Вызывается один раз при первом создании сервиса методом startService(). Не вызывается при повторном использовании метода startService().
– onStartCommand()
Вызывается каждый раз при получении сервисом команды, отправленной с помощью метода startService(). Метод может возвращать флаг, который запускает сервис в определённом режиме
– onBind()
Вызывается при привязке (сервис живёт, пока жив клиент) сервиса к клиенту (Activity) при помощью метода bindService()
– onRebind()
Вызывается при повторной привязке сервиса к клиенту
– onUnbind()
Вызывается при отвязке сервиса от клиента
– onDestroy()
Вызывается при уничтожении сервиса
2. Какие существуют разновидности сервисов?
Сервисы можно разделить на три вида:
– Foreground Service
Сервис запущенный в данном режиме имеет высокий приоритет и не будет уничтожен системой, в случае нехватки памяти. Такой Service связывается с Notification, которое будет отображаться в статус баре. Запускается при помощи метода startForeground().
– Background Service
Работает в стандартном режиме, в фоне, в основном потоке приложения. Запускается при помощи метода startService().
– Bound Service
Service запущенный в данном режиме привязывается к какому-либо клиенту, например к Activity, и работает по принципу клиент-сервер. Service может быть привязан к нескольким клиентам, при этом система уничтожит сервис в случае, если все клиенты связанные с ним были уничтожены. Запускается при помощи метода bindService(). Для открепления сервиса от клиента используется метод unbindService(). При помощи интерфейса IBinder можно получить ссылку на наш сервис и вызывать методы непосредственно в нашем сервисе.
3. Что такое Intent Service?
Intent Service – наследник класса Service. В отличие от Service, выполняется асинхронно в отдельном потоке. Сервис запускается методом startService() в котором передается Intent с необходимыми данными для работы. Обрабатывает входящий Intent в методе onHandleIntent(). После завершения всех необходимых операций над данными сервис прекращает свою работу.
4. Какие флаги запуска можно задать сервису?
Метод жизненного цикла сервиса onStartCommand()С может возвращать флаг, который описывает поведение сервиса, в случае если он был неожиданно остановлен, например системой из-за нехватки памяти:
– START_STICKY
Сервис будет заново запущен системой и продолжит работу
– START_REDELIVER_INTENT
Сервис будет заново запущен системой и заново получит Intent который был передан методом startService() при запуске сервиса
– START_NOT_STICKY
Сервис остается в остановленном положении и не будет заново запущен системой
– STOP_FOREGROUND_REMOVE
Используется для отмены режима foreground и удаления Notification с которым связан сервис.