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 с локално излъчване, механизмът 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също