Background Service è un componente Android progettato per eseguire operazioni lunghe in background senza interfaccia utente. A differenza di Activity, Service continua a funzionare anche dopo che l’app viene minimizzata o l’utente passa a un’altra app. Secondo Android Developers, 2026, esistono tre tipi di servizi: Started Service, Bound Service e Foreground Service, ciascuno con il proprio ciclo di vita e ambito di applicazione.
Punti chiave
Background Service (o semplicemente Service) è uno dei quattro componenti fondamentali di un’applicazione Android, insieme ad Activity, BroadcastReceiver e ContentProvider. A differenza di Activity, Service non ha un’interfaccia visiva ed è progettato per eseguire operazioni che devono continuare indipendentemente dal fatto che l’app sia in primo piano o meno.
Service viene eseguito sul thread principale dell’applicazione, quindi qualsiasi operazione bloccante al suo interno richiede la creazione di un thread separato. In caso contrario, il sistema genererà un ANR (Application Not Responding). Per semplici operazioni in background, Android fornisce IntentService, che crea automaticamente un thread di lavoro. Nei progetti moderni, si consiglia di utilizzare le coroutine Kotlin con CoroutineScope all’interno di Service per l’elaborazione asincrona senza bloccare il thread principale.
Lo scopo principale di Service è la riproduzione musicale, il download di file, la gestione delle richieste di rete, la sincronizzazione dei dati e altre attività che devono continuare dopo che l’utente lascia l’app. Tuttavia, da Android 8, gli sviluppatori devono scegliere consapevolmente tra i tipi di servizio, tenendo conto delle restrizioni del lavoro in background.
Service ha il proprio ciclo di vita, che differisce da Activity. Include quattro metodi chiave: onCreate, onStartCommand, onBind e onDestroy. Comprendere questo ciclo è essenziale per implementare correttamente le attività in background senza perdite di memoria.
Il metodo onCreate viene chiamato alla creazione del servizio, una volta durante la sua vita. Qui vengono inizializzate risorse come timer, connessioni al database e socket. Il metodo onStartCommand viene chiamato ogni volta che viene invocato startService, consentendo di inviare comandi a un servizio già in esecuzione. Il valore restituito determina il comportamento del sistema al riavvio.
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 viene chiamato quando si lega un servizio tramite bindService e restituisce un oggetto IBinder per l’interazione con il client. Questo metodo viene utilizzato solo per Bound Service. onDestroy è l’ultima chiamata prima della distruzione del servizio. Qui vengono rilasciate tutte le risorse, fermati i thread e annullate le attività.
Android offre tre tipi di Service, ciascuno progettato per il proprio scenario. Scegliere il tipo sbagliato può portare a un comportamento instabile dell’app o a un consumo eccessivo della batteria.
Started Service viene avviato chiamando startService e funge fino a quando non chiama stopSelf o stopService. È adatto per attività che devono essere eseguite immediatamente: invio di analisi, elaborazione di un’immagine, download di un singolo file. Dopo aver completato il lavoro, il servizio si ferma da solo.
Bound Service fornisce un’interfaccia client-server, consentendo ad Activity, Fragment o altro componente di interagire con il servizio. Il servizio vive fino a quando c’è almeno un client collegato. Quando tutti i client si scollegano, il servizio viene distrutto. Bound Service è utile per attività che richiedono comunicazione bidirezionale: lettore musicale, navigazione.
Foreground Service è uno Started Service con una notifica persistente nella barra di stato. Il sistema considera tale servizio come attivo e non lo uccide nemmeno in caso di poca memoria. Foreground Service è obbligatorio per la riproduzione musicale, la registrazione audio, il tracciamento della posizione e altre attività importanti per l’utente.
| Parametro | Started | Bound | Foreground |
|---|---|---|---|
| Avvio | startService | bindService | startForeground |
| Durata | fino a stopSelf | fino a quando ci sono client | fino a stopForeground |
| Notifica | no | no | obbligatoria |
| Uccidibile | sì | sì | no |
| Esempio | download | lettore | musica |
Creare un servizio inizia dichiarando una classe che eredita da Service e registrandola in AndroidManifest.xml. Senza la registrazione nel manifest, il sistema non sarà in grado di avviare il servizio e qualsiasi chiamata a startService provocherà un’eccezione.
// Registrazione in 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
}
}
Per avviare un servizio da un’Activity o un Fragment, viene utilizzato un Intent con un riferimento esplicito alla classe del servizio. A partire da Android 8, Foreground Service richiede l’autorizzazione FOREGROUND_SERVICE nel manifest.
// Avviare un Started Service
val intent = Intent(this, SyncService::class.java)
intent.putExtra("action", "sync")
startService(intent)
// Avviare un Foreground Service (Android 8+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent)
} else {
startService(intent)
}
A partire da Android 8 (API 26), Google ha introdotto restrizioni severe sui servizi in background. L’avvio di un servizio in background (quando l’app non è in primo piano) è consentito solo in casi eccezionali: alla ricezione di una notifica push, dopo l’avvio del dispositivo o tramite JobScheduler.
Per attività lunghe che non richiedono esecuzione immediata, si consiglia di utilizzare WorkManager o JobScheduler. Se un’app ha realmente bisogno di un servizio in esecuzione, l’unico modo è un Foreground Service con una notifica visibile all’utente. Avviare un servizio senza notifica in background verrà ignorato dal sistema.
JobIntentService è una classe specializzata apparsa nella libreria di supporto per funzionare su Android 5+. Combina il comportamento di IntentService (thread di lavoro automatico, elaborazione sequenziale) con la pianificazione tramite JobScheduler. Su Android 8+, JobIntentService utilizza internamente JobScheduler, mentre sulle versioni precedenti usa un Service normale. Ciò consente una gestione uniforme delle attività in background senza controlli aggiuntivi della versione 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")
// Eseguito in un thread in background
uploadFile(fileUri)
}
}
Uno dei problemi comuni quando si lavora con Background Service sono le perdite di memoria. Poiché un Service può vivere più a lungo di un’Activity, i riferimenti all’Activity all’interno di Service (tramite listener, callback o broadcast) impediscono la garbage collection dei componenti UI. Si consiglia di utilizzare WeakReference, ViewModel o LiveData per la comunicazione Service-UI. In onDestroy, assicurati di annullare tutti gli abbonamenti, fermare i thread e chiudere i cursori.
La scelta tra Background Service e WorkManager dipende dallo scenario. Service è adatto per attività che devono essere eseguite immediatamente e continuamente: riproduzione musicale, registrazione audio, tracciamento GPS. WorkManager è migliore per attività differite e garantite: sincronizzazione, invio di analisi, upload di log. WorkManager sopravvive ai riavvii del dispositivo, mentre Service no. Service può essere in primo piano con notifica, mentre WorkManager funziona silenziosamente in background. In pratica, gli sviluppatori combinano entrambi gli approcci: Foreground Service per attività critiche per l’utente e WorkManager per la manutenzione in background.
Android 12 ha introdotto il flag android:foregroundServiceType, che richiede di specificare il tipo di servizio: dataSync, camera, connectedDevice, location, mediaPlayback e altri. La specifica errata del tipo causa un’eccezione all’avvio. Questa pratica rende Background Service più trasparente sia per l’utente che per il sistema.
La corretta registrazione di Service nel manifest include l’attributo exported (accessibilità per app esterne), foregroundServiceType (tipo di servizio in background su Android 12+) e l’autorizzazione. Per Bound Service, è necessario dichiarare anche android:permission="android.permission.BIND_JOB_SERVICE" per JobIntentService. Senza la registrazione nel manifest, qualsiasi chiamata a startService o bindService genererà un’eccezione, quindi la verifica del manifest è il primo passo nella diagnosi dei problemi relativi a Service.
Domande frequenti
Service viene eseguito sul thread principale (UI Thread) dell’applicazione. Qualsiasi operazione bloccante all’interno di onStartCommand o onHandleIntent deve essere spostata in un thread separato o in una coroutine, altrimenti il sistema genererà un ANR dopo 5 secondi.
IntentService è una sottoclasse di Service che crea automaticamente un thread di lavoro ed elabora i comandi in sequenza. Dopo aver completato l’ultima attività, IntentService si ferma da solo. A partire da Android 8, IntentService è considerato deprecato a favore di JobIntentService o WorkManager.
Avviare un Started Service dallo sfondo su Android 12 è vietato. L’eccezione è un Foreground Service con foregroundServiceType dichiarato nel manifest e una notifica valida. È consentito anche un avvio breve dopo aver ricevuto un messaggio FCM ad alta priorità.
Esistono tre metodi: BroadcastReceiver con broadcast locale, il meccanismo Messenger tramite Handler e LiveData/Flow nell’architettura MVVM con un ViewModel condiviso. Per Bound Service, viene utilizzato IBinder con chiamate dirette ai metodi.
Se un Service è stato avviato con il flag START_STICKY, il sistema lo riavvierà dopo che il processo è stato ucciso per mancanza di memoria. Il flag START_NOT_STICKY significa che il sistema non riavvierà il servizio. START_REDELIVER_INTENT è simile a START_STICKY ma consegna l’ultimo Intent.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche