Background Service — це компонент Android, призначений для виконання тривалих операцій у фоновому режимі без інтерфейсу користувача. На відміну від Activity, Service продовжує працювати навіть після того, як додаток згорнуто або користувач переключився на інший додаток. За даними Android Developers, 2026, існує три типи сервісів: Started Service, Bound Service та Foreground Service, кожен зі своїм життєвим циклом та областю застосування.
Головне
Background Service (або просто Service) — один з чотирьох основних компонентів Android-додатка поряд з Activity, BroadcastReceiver та ContentProvider. На відміну від Activity, Service не має візуального інтерфейсу і призначений для виконання операцій, які мають тривати незалежно від того, чи знаходиться додаток на передньому плані чи ні.
Service працює в головному потоці (main thread) додатка, тому будь-які блокуючі операції всередині нього вимагають створення окремого потоку. Якщо цього не зробити, система викличе ANR (Application Not Responding). Для простих фонових операцій Android надає IntentService, який автоматично створює робочий потік. У сучасних проектах рекомендується використовувати Kotlin-корутини з CoroutineScope всередині Service для асинхронної обробки без блокування головного потоку.
Основне призначення Service — відтворення музики, завантаження файлів, робота з мережевими запитами, синхронізація даних та інші завдання, які мають тривати після виходу користувача з додатка. Однак з виходом Android 8 розробникам доводиться обирати між типами сервісів усвідомлено, враховуючи обмеження фонової роботи.
Service має власний життєвий цикл, який відрізняється від Activity. Він включає чотири ключові методи: onCreate, onStartCommand, onBind та onDestroy. Розуміння цього циклу необхідне для коректної реалізації фонових завдань без витоків пам'яті.
Метод onCreate викликається при створенні сервісу, одноразово за час його життя. У ньому ініціалізуються ресурси: таймери, підключення до бази даних, сокети. Метод onStartCommand викликається щоразу при виклику startService, що дозволяє передавати команди вже працюючому сервісу. Значення, що повертається, визначає поведінку системи при перезапуску.
class DownloadService : Service() {
override fun onCreate() {
super.onCreate()
initializeDownloader()
}
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
downloadFile(intent?.getStringExtra("url"))
return START_STICKY
}
override fun onBind(intent: Intent): IBinder? = null
}
onBind викликається при прив'язці сервісу через bindService та повертає об'єкт IBinder для взаємодії з клієнтом. Цей метод використовується тільки для Bound Service. onDestroy — останній виклик перед знищенням сервісу. У ньому звільняються всі ресурси, зупинені потоки та скасовані завдання.
Android пропонує три типи Service, кожен з яких призначений для свого сценарію. Вибір неправильного типу може призвести до нестабільної роботи додатка або витрати заряду батареї.
Started Service запускається викликом startService та працює доти, доки не викличе stopSelf або stopService. Він підходить для завдань, які мають бути виконані негайно: відправка аналітики, обробка зображення, завантаження одного файлу. Після завершення роботи сервіс зупиняється самостійно.
Bound Service надає клієнт-серверний інтерфейс, дозволяючи Activity, Fragment або іншому компоненту взаємодіяти з сервісом. Сервіс живе, доки є хоча б один пов'язаний клієнт. Коли всі клієнти відв'язуються, сервіс знищується. Bound Service зручний для завдань, що вимагають двостороннього зв'язку: музичний плеєр, навігація.
Foreground Service — це Started Service з постійним сповіщенням у статус-барі. Система вважає такий сервіс активним і не вбиває його навіть при нестачі пам'яті. Foreground Service обов'язковий для відтворення музики, запису аудіо, відстеження місцезнаходження та інших завдань, важливих для користувача.
| Параметр | Started | Bound | Foreground |
|---|---|---|---|
| Запуск | startService | bindService | startForeground |
| Життя | до stopSelf | поки є клієнти | до stopForeground |
| Сповіщення | ні | ні | обов'язково |
| Вбивається | так | так | ні |
| Приклад | завантаження | плеєр | музика |
Створення сервісу починається з оголошення класу, що наслідує від Service, та реєстрації його в AndroidManifest.xml. Без реєстрації в маніфесті система не зможе запустити сервіс, і будь-який виклик startService призведе до виключення.
// Реєстрація в AndroidManifest.xml
@SuppressLint("ForegroundServiceType")
class SyncService : Service() {
override fun onStartCommand(
intent: Intent?,
flags: Int,
startId: Int
): Int {
startForeground(
NOTIFICATION_ID,
createNotification()
)
performSync(intent)
return START_NOT_STICKY
}
}
Для запуску сервісу з Activity або Fragment використовується Intent з явним зазначенням класу сервісу. Починаючи з Android 8, для Foreground Service обов'язково потрібен дозвіл FOREGROUND_SERVICE в маніфесті.
// Запуск Started Service
val intent = Intent(this, SyncService::class.java)
intent.putExtra("action", "sync")
startService(intent)
// Запуск Foreground Service (Android 8+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
Починаючи з Android 8 (API 26) Google ввів строгі обмеження на фонові сервіси. фоновий запуск Service (коли додаток не на передньому плані) дозволений тільки у виняткових випадках: при отриманні push-сповіщення, після завантаження пристрою або через JobScheduler.
Для тривалих завдань, що не вимагають негайного виконання, рекомендується використовувати WorkManager або JobScheduler. Якщо ж додатку дійсно потрібен працюючий сервіс, єдиний спосіб — Foreground Service зі сповіщенням, яке бачить користувач. Запуск сервісу без сповіщення у фоні буде проігнорований системою.
JobIntentService — це спеціалізований клас, який з'явився в support library для роботи на Android 5+. Він поєднує поведінку IntentService (автоматичний робочий потік, послідовна обробка) з плануванням через JobScheduler. На Android 8+ JobIntentService використовує JobScheduler під капотом, а на старіших версіях — звичайний Service. Це дозволяє одноманітно обробляти фонові завдання без додаткових перевірок версії Android.
class UploadJobService : JobIntentService() {
companion object {
private const val JOB_ID = 1000
fun enqueueWork(context: Context, work: Intent) {
enqueueWork(
context,
UploadJobService::class.java,
JOB_ID,
work
)
}
}
override fun onHandleWork(intent: Intent) {
val fileUri = intent.getStringExtra("file_uri")
// Виконується у фоновому потоці
uploadFile(fileUri)
}
}
Одна з частих проблем при роботі з Background Service — витоки пам'яті. Оскільки Service може жити довше, ніж Activity, посилання на Activity всередині Service (через listener, callback або broadcast) призводять до неможливості збирання сміття для UI-компонентів. Рекомендується використовувати WeakReference, ViewModel або LiveData для зв'язку Service з UI. В onDestroy обов'язково скасовувати всі підписки, зупиняти потоки та закривати курсори.
Вибір між Background Service та WorkManager залежить від сценарію. Service підходить для завдань, які мають виконуватися негайно та безперервно: відтворення музики, запис аудіо, відстеження GPS. WorkManager краще для відкладених, гарантованих завдань: синхронізація, відправка аналітики, завантаження логів. WorkManager переживе перезавантаження пристрою, а Service — ні. Service може бути Foreground зі сповіщенням, а WorkManager працює тихо у фоні. На практиці розробники комбінують обидва підходи: Foreground Service для критичних користувацьких завдань та WorkManager для фонового обслуговування.
Android 12 ввів прапорець android:foregroundServiceType, який вимагає вказувати тип служби: dataSync, camera, connectedDevice, location, mediaPlayback та інші. Неправильне зазначення типу призводить до виключення при запуску. Ця практика робить Background Service більш прозорим для користувача та системи.
Правильна реєстрація Service в маніфесті включає атрибути exported (доступність для зовнішніх додатків), foregroundServiceType (тип фонової служби на Android 12+) та permission. Для Bound Service також потрібно оголосити android:permission="android.permission.BIND_JOB_SERVICE" для JobIntentService. Без реєстрації в маніфесті будь-який виклик startService або bindService завершиться виключенням, тому перевірка маніфесту — перший крок при діагностиці проблем з Service.
Часті запитання
Service виконується в головному потоці (UI Thread) додатка. Будь-яка блокуюча операція всередині onStartCommand або onHandleIntent має бути винесена в окремий потік або корутину, інакше система викличе ANR через 5 секунд.
IntentService — це нащадок Service, який автоматично створює робочий потік та обробляє команди послідовно. Після завершення останнього завдання IntentService зупиняється сам. Починаючи з Android 8 IntentService вважається застарілим на користь JobIntentService або WorkManager.
Запуск Started Service з фону на Android 12 заборонений. Виняток — Foreground Service з оголошеним foregroundServiceType в маніфесті та валідним сповіщенням. Також дозволений короткий старт після отримання високопріоритетного FCM-повідомлення.
Існує три способи: BroadcastReceiver з локальним broadcast, механізм Messenger через Handler, та LiveData/Flow в архітектурі MVVM зі спільним ViewModel. Для Bound Service використовується IBinder з прямим викликом методів.
Якщо Service був запущений з прапорцем START_STICKY, система перезапустить його після знищення процесу при нестачі пам'яті. Прапорець START_NOT_STICKY означає, що система не буде перезапускати сервіс. START_REDELIVER_INTENT аналогічний START_STICKY, але передає останній Intent.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також