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. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође