I servizi in primo piano eseguono operazioni visibili all'utente.
I servizi in primo piano mostrano una notifica nella barra di stato per informare gli utenti che la tua app sta eseguendo un'attività in primo piano e consuma risorse di sistema.
Ecco alcuni esempi di app che utilizzano i servizi in primo piano:
- Un'app di lettore musicale che riproduce musica in un servizio in primo piano. La notifica potrebbe mostrare il brano in riproduzione.
- Un'app per l'attività fisica che registra l'esecuzione di un utente in un servizio in primo piano, dopo aver ricevuto l'autorizzazione dall'utente. La notifica potrebbe mostrare la distanza percorsa dall'utente durante la sessione di fitness corrente.
Utilizza un servizio in primo piano solo quando la tua app deve eseguire un'attività visibile all'utente, anche quando non interagisce direttamente con l'app. Se l'azione ha un'importanza sufficientemente limitata e vuoi utilizzare una notifica con priorità minima, crea un'attività in background.
Questo documento descrive l'autorizzazione richiesta per utilizzare i servizi in primo piano e come avviare un servizio in primo piano e rimuoverlo. Descrive inoltre come associare determinati casi d'uso ai tipi di servizi in primo piano e le limitazioni di accesso che hanno effetto quando si avvia un servizio in primo piano da un'app in esecuzione in background.
L'utente può ignorare la notifica per impostazione predefinita
A partire da Android 13 (livello API 33), per impostazione predefinita gli utenti possono ignorare la notifica associata a un servizio in primo piano. Per farlo, gli utenti eseguono un gesto di scorrimento sulla notifica. Tradizionalmente, la notifica non viene ignorata, a meno che il servizio in primo piano non venga interrotto o rimosso dal primo piano.
Se vuoi che la notifica non possa essere ignorata dall'utente, passa true
al metodo setOngoing()
quando crei la notifica utilizzando Notification.Builder
.
Servizi che mostrano una notifica immediatamente
Se un servizio in primo piano ha almeno una delle seguenti caratteristiche, il sistema mostra la notifica associata subito dopo l'avvio del servizio, anche sui dispositivi con Android 12 o versioni successive:
- Il servizio è associato a una notifica che include i pulsanti di azione.
- Il servizio ha un valore
foregroundServiceType
dimediaPlayback
,mediaProjection
ophoneCall
. - Il servizio fornisce un caso d'uso relativo a telefonate, navigazione o riproduzione di contenuti multimediali, come definito nell'attributo categoria della notifica.
- Il servizio ha disattivato la modifica del comportamento passando
FOREGROUND_SERVICE_IMMEDIATE
asetForegroundServiceBehavior()
durante la configurazione della notifica.
Su Android 13 (livello API 33) o versioni successive, se l'utente nega l'autorizzazione alle notifiche, visualizzerà comunque avvisi relativi ai servizi in primo piano in Task Manager, ma non le vedrà nel riquadro a scomparsa delle notifiche.
Dichiara i servizi in primo piano nel tuo manifest
Nel file manifest dell'app, dichiara ogni servizio in primo piano dell'app con un elemento <service>
. Per ogni servizio, utilizza un attributo android:foregroundServiceType
per dichiarare il tipo di lavoro svolto.
Ad esempio, se la tua app crea un servizio in primo piano che riproduce musica, puoi dichiarare il servizio nel seguente modo:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
Se i diversi tipi si applicano al servizio, separali con l'operatore |
. Ad esempio, un servizio che utilizza la fotocamera e il microfono dichiarerebbe come segue:
android:foregroundServiceType="camera|microphone"
Richiedere le autorizzazioni del servizio in primo piano
Le app destinate ad Android 9 (livello API 28) o versioni successive che utilizzano i servizi in primo piano
devono richiedere l'elemento
FOREGROUND_SERVICE
nel file manifest dell'app, come mostrato nel seguente snippet di codice. Si tratta di un'autorizzazione normale, quindi il sistema la concede automaticamente all'app richiedente.
Inoltre, se l'app ha come target il livello API 34 o superiore, deve richiedere il tipo di autorizzazione appropriato per il tipo di lavoro che eseguirà il servizio in primo piano. A ogni tipo di servizio in primo piano corrisponde un tipo di autorizzazione. Ad esempio, se un'app avvia un servizio in primo piano che utilizza la fotocamera, devi richiedere entrambe le autorizzazioni FOREGROUND_SERVICE
e FOREGROUND_SERVICE_CAMERA
. Sono tutte autorizzazioni normali, pertanto il sistema le concede automaticamente se sono elencate nel manifest.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
<application ...>
...
</application>
</manifest>
Prerequisiti per i servizi in primo piano
A partire da Android 14 (livello API 34), quando avvii un servizio in primo piano, il sistema verifica la presenza di prerequisiti specifici in base al tipo di servizio. Ad esempio, se provi ad avviare un servizio in primo piano di tipo location
, il sistema controlla che la tua app disponga già dell'autorizzazione ACCESS_COARSE_LOCATION
o ACCESS_FINE_LOCATION
. In caso contrario, il sistema genera
SecurityException
.
Per questo motivo, devi verificare che i prerequisiti richiesti siano soddisfatti prima di avviare un servizio in primo piano. La documentazione relativa al tipo di servizio in primo piano elenca i prerequisiti richiesti per ogni tipo di servizio in primo piano.
Avvia un servizio in primo piano
Prima di richiedere al sistema di eseguire un servizio come servizio in primo piano, avvia il servizio stesso:
Kotlin
val intent = Intent(...) // Build the intent for the service context.startForegroundService(intent)
Java
Context context = getApplicationContext(); Intent intent = new Intent(...); // Build the intent for the service context.startForegroundService(intent);
All'interno del servizio, di solito in onStartCommand()
, puoi richiederne
l'esecuzione in primo piano. Per farlo, chiama
ServiceCompat.startForeground()
(disponibile in androidx-core 1.12 e versioni successive). Questo metodo accetta i seguenti
parametri:
- Il servizio
- Un numero intero positivo che identifica in modo univoco la notifica nella barra di stato
- L'oggetto
Notification
stesso - I tipi di servizi in primo piano che identificano il lavoro svolto dal servizio
Questi tipi possono essere un sottoinsieme dei tipi dichiarati nel manifest, a seconda del caso d'uso specifico. Poi, se devi aggiungere altri tipi di servizi,
puoi chiamare di nuovo startForeground()
.
Ad esempio, supponi che un'app per l'attività fisica esegua un servizio di monitoraggio della corsa che necessita sempre di informazioni location
, ma potrebbe o meno avere bisogno di riprodurre contenuti multimediali. Devi
dichiarare sia location
sia mediaPlayback
nel file manifest. Se un
utente inizia una corsa e vuole che la sua posizione venga monitorata, la tua app deve chiamare
startForeground()
e trasmettere solo l'autorizzazione ACCESS_FINE_LOCATION
. Quindi,
se l'utente vuole avviare la riproduzione dell'audio, chiama di nuovo startForeground()
e
trasmetti la combinazione bit a bit di tutti i tipi di servizi in primo piano (in questo caso,
ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
Ecco un esempio che avvia un servizio in primo piano della fotocamera:
Kotlin
class MyCameraService: Service() { private fun startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user has // granted the CAMERA permission. val cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the foreground // Consider informing user or updating your app UI if visible. stopSelf() return } try { val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service is running .build() ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA } else { 0 }, ) } catch (e: Exception) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e is ForegroundServiceStartNotAllowedException) { // App not in a valid state to start foreground service // (e.g. started from bg) } // ... } } }
Java
public class MyCameraService extends Service { private void startForeground() { // Before starting the service as foreground check that the app has the // appropriate runtime permissions. In this case, verify that the user // has granted the CAMERA permission. int cameraPermission = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA); if (cameraPermission == PackageManager.PERMISSION_DENIED) { // Without camera permissions the service cannot run in the // foreground. Consider informing user or updating your app UI if // visible. stopSelf(); return; } try { Notification notification = new NotificationCompat.Builder(this, "CHANNEL_ID") // Create the notification to display while the service // is running .build(); int type = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { type = ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; } ServiceCompat.startForeground( /* service = */ this, /* id = */ 100, // Cannot be 0 /* notification = */ notification, /* foregroundServiceType = */ type ); } catch (Exception e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && e instanceof ForegroundServiceStartNotAllowedException ) { // App not in a valid state to start foreground service // (e.g started from bg) } // ... } } //... }
Rimuovere un servizio dal primo piano
Per rimuovere il servizio dal primo piano, chiama stopForeground()
.
Questo metodo utilizza un valore booleano, che indica se rimuovere anche la notifica della barra di stato. Tieni presente che il servizio continua a essere eseguito.
Se interrompi il servizio mentre viene eseguito in primo piano, la relativa notifica viene rimossa.
Gestire l'interruzione avviata dall'utente delle app che eseguono servizi in primo piano
A partire da Android 13 (livello API 33), gli utenti possono completare un flusso di lavoro dal riquadro a scomparsa delle notifiche per interrompere un'app con un servizio in primo piano in corso, indipendentemente dalla versione dell'SDK target dell'app. Questa accessibilità, denominata Task Manager, mostra un elenco delle app che attualmente eseguono un servizio in primo piano.
Questo elenco è denominato App attive. Accanto a ogni app è presente un pulsante Interrompi. La figura 1 illustra il flusso di lavoro di Task Manager su un dispositivo che esegue Android 13.
Quando l'utente preme il pulsante Interrompi accanto alla tua app in Task Manager, si verificano le seguenti azioni:
- Il sistema rimuove la tua app dalla memoria. Di conseguenza, l'intera app si interrompe, non solo il servizio in primo piano in esecuzione.
- Il sistema rimuove lo stack di attività dell'app.
- La riproduzione di contenuti multimediali si interrompe.
- La notifica associata al servizio in primo piano viene rimossa.
- La tua app rimane nella cronologia.
- I job pianificati vengono eseguiti all'orario pianificato.
- Le sveglie suonano all'ora o alla finestra temporale programmata.
Per verificare che la tua app si comporti come previsto mentre e dopo che un utente la interrompe, esegui questo comando ADB in una finestra del terminale:
adb shell cmd activity stop-app PACKAGE_NAME
Esenzioni
Il sistema offre diversi livelli di esenzioni per determinati tipi di app, descritti nelle sezioni seguenti.
Le esenzioni si applicano a livello di app, non di procedura. Se il sistema esenta un processo in un'app, sono esenti anche tutti gli altri processi nell'app.
Esenzioni dalla visualizzazione nel Task Manager
Le seguenti app possono eseguire un servizio in primo piano e non essere visualizzate in Tasks:
- App a livello di sistema
- App per la sicurezza, ovvero app con il ruolo
ROLE_EMERGENCY
- Dispositivi in modalità demo
Esenzioni dall'interruzione da parte degli utenti
Quando i seguenti tipi di app eseguono un servizio in primo piano, vengono visualizzati in Task Manager, ma accanto al nome dell'app non è presente un pulsante Interrompi che l'utente possa toccare:
- App del proprietario del dispositivo
- App del proprietario del profilo
- App permanenti
- App con il ruolo
ROLE_DIALER
Usa API appositamente create anziché servizi in primo piano
Per molti casi d'uso, esistono API Platform o Jetpack utilizzabili per lavorare, per cui altrimenti potresti utilizzare un servizio in primo piano. Se esiste un'API creata appositamente, dovresti quasi sempre utilizzarla anziché utilizzare un servizio in primo piano. Le API create appositamente forniscono spesso funzionalità aggiuntive specifiche per i diversi casi d'uso che altrimenti dovrebbero essere create autonomamente. Ad esempio, l' API Bubbles gestisce la complessa logica dell'interfaccia utente per le app di messaggistica che devono implementare le funzionalità dei fumetti di chat.
La documentazione relativa ai tipi di servizi in primo piano elenca delle buone alternative da utilizzare al posto dei servizi in primo piano.
Limitazioni relative all'avvio di un servizio in primo piano in background
Le app destinate ad Android 12 o versioni successive non possono avviare i servizi in primo piano mentre sono in esecuzione in background, ad eccezione di alcuni casi speciali. Se un'app tenta di avviare un servizio in primo piano mentre è in esecuzione in background e il servizio in primo piano non soddisfa uno dei casi eccezionali, il sistema genera un elemento ForegroundServiceStartNotAllowedException
.
Inoltre, se un'app vuole lanciare un servizio in primo piano che richiede le autorizzazioni durante l'uso (ad esempio, sensore del corpo, fotocamera, microfono o autorizzazioni di posizione), non può creare il servizio mentre l'app è in background, anche se rientra in una delle esenzioni dalle restrizioni relative all'avvio in background. Il motivo di questo problema è spiegato nella sezione Restrizioni relative all'avvio dei servizi in primo piano che richiedono autorizzazioni durante l'uso.
Esenzioni dalle limitazioni relative all'avvio in background
Nei seguenti casi, la tua app può avviare i servizi in primo piano anche mentre l'app è in esecuzione in background:
- L'app passa da uno stato visibile all'utente, ad esempio un'attività.
- La tua app può avviare un'attività in background, tranne nel caso in cui l'app abbia un'attività nello stack precedente di un'attività esistente.
L'app riceve un messaggio con priorità elevata utilizzando Firebase Cloud Messaggi.
L'utente esegue un'azione su un elemento dell'interfaccia utente correlato alla tua app. Ad esempio, potrebbe interagire con un bolla, una notifica, un widget o un'attività.
L'app richiama un allarme esatto per completare un'azione richiesta dall'utente.
La tua app è l'attuale metodo di inserimento del dispositivo.
La tua app riceve un evento correlato alla geofencing o alla transizione del riconoscimento attività.
Dopo il riavvio del dispositivo e la ricezione dell'azione dell'intent
ACTION_BOOT_COMPLETED
,ACTION_LOCKED_BOOT_COMPLETED
oACTION_MY_PACKAGE_REPLACED
in un ricevitore di trasmissione.L'app riceve l'azione dell'intent
ACTION_TIMEZONE_CHANGED
,ACTION_TIME_CHANGED
oACTION_LOCALE_CHANGED
in un ricevitore broadcast.La tua app riceve l'evento
ACTION_TRANSACTION_DETECTED
daNfcService
.App con determinati ruoli o autorizzazioni di sistema, ad esempio proprietari del dispositivo e proprietari del profilo.
L'app utilizza Gestione dispositivi companion e dichiara l'autorizzazione
REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
oREQUEST_COMPANION_RUN_IN_BACKGROUND
. Se possibile, utilizzaREQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND
.La tua app contiene l'autorizzazione
SYSTEM_ALERT_WINDOW
.L'utente disattiva le ottimizzazioni della batteria per la tua app.
Limitazioni relative all'avvio di servizi in primo piano che richiedono autorizzazioni durante l'uso
Su Android 14 (livello API 34) o versioni successive, esistono situazioni speciali da tenere presenti se stai avviando un servizio in primo piano che richiede autorizzazioni durante l'uso.
Se la tua app ha come target Android 14 o versioni successive, il sistema operativo controlla quando crei un servizio in primo piano per verificare che l'app disponga di tutte le autorizzazioni appropriate per quel tipo di servizio. Ad esempio, quando crei un servizio in primo piano di tipo microfono, il sistema operativo verifica che l'app attualmente disponga dell'autorizzazione RECORD_AUDIO
. Se non hai questa autorizzazione, il sistema genera un SecurityException
.
Questo causa un potenziale problema per le autorizzazioni in uso. Se la tua app ha un'autorizzazione durante l'uso, l'autorizzazione dispone solo mentre si trova in primo piano. Ciò significa che se la tua app è in background e cerca di creare un servizio in primo piano di tipo fotocamera, posizione o microfono, il sistema vede che l'app non dispone al momento delle autorizzazioni richieste e genera un'SecurityException
.
Analogamente, se l'app è in background e crea un servizio sanitario che richiede l'autorizzazione BODY_SENSORS_BACKGROUND
, al momento l'app non dispone di questa autorizzazione e il sistema genera un'eccezione.
Ciò non si applica se si tratta di un servizio sanitario che ha bisogno di autorizzazioni diverse, come ACTIVITY_RECOGNITION
. La chiamata a ContextCompat.checkSelfPermission()
non evita questo problema. Se la tua app ha un'autorizzazione durante l'uso e
chiama checkSelfPermission()
per verificare se dispone di questa autorizzazione, il metodo restituisce PERMISSION_GRANTED
anche se l'app è in background. Quando il metodo restituisce PERMISSION_GRANTED
, significa che la tua app ha questa autorizzazione mentre l'app è in uso.
Per questo motivo, se il servizio in primo piano richiede un'autorizzazione durante l'uso, devi chiamare Context.startForegroundService()
o Context.bindService()
quando la tua app ha un'attività visibile, a meno che il servizio non rientri in una delle esenzioni definite.
Esenzioni dalle limitazioni relative alle autorizzazioni durante l'uso
In alcune situazioni, anche se un servizio in primo piano viene avviato mentre l'app è in esecuzione in background, può comunque accedere alle informazioni su posizione, fotocamera e microfono mentre l'app è in esecuzione in primo piano ("durante l'uso").
Nelle stesse situazioni, se il servizio dichiara un tipo di servizio in primo piano location
e viene avviato da un'app che dispone dell'autorizzazione ACCESS_BACKGROUND_LOCATION
, il servizio può accedere sempre alle informazioni sulla posizione, anche quando l'app è in esecuzione in background.
Il seguente elenco contiene le seguenti situazioni:
- Un componente di sistema avvia il servizio.
- Il servizio inizia interagendo con i widget delle app.
- Il servizio inizia interagendo con una notifica.
- Il servizio inizia come
PendingIntent
inviato da un'app diversa e visibile. - Il servizio viene avviato da un'app che è un controller dei criteri dei dispositivi che viene eseguito in modalità proprietario del dispositivo.
- Il servizio si avvia da un'app che fornisce
VoiceInteractionService
. - Il servizio viene avviato da un'app che dispone dell'autorizzazione con privilegi
START_ACTIVITIES_FROM_BACKGROUND
.
Determina quali servizi sono interessati nella tua app
Quando testi la tua app, avvia i relativi servizi in primo piano. Se un servizio avviato ha limitato l'accesso alla posizione, al microfono e alla fotocamera, in Logcat viene visualizzato il seguente messaggio:
Foreground service started from background can not have \ location/camera/microphone access: service SERVICE_NAME