Per avviare un servizio in primo piano dalla tua app, devi seguire due passaggi. Innanzitutto, devi avviare il servizio chiamando context.startForegroundService(). Quindi, fai in modo che il servizio chiami ServiceCompat.startForeground() per promuoversi a servizio in primo piano.
Prerequisiti
A seconda del livello API scelto come target per la tua app, esistono alcune limitazioni su quando un'app può avviare un servizio in primo piano.
Le app che hanno come target Android 12 (livello API 31) o versioni successive non possono avviare un servizio in primo piano mentre l'app è in background, con alcune eccezioni specifiche. Per saperne di più e per informazioni sulle eccezioni a questa regola, consulta Limitazioni all'avvio di un servizio in primo piano dal background.
Le app che hanno come target Android 14 (livello API 34) o versioni successive devono richiedere le autorizzazioni appropriate per il tipo di servizio in primo piano. Quando l'app tenta di promuovere un servizio in primo piano, il sistema verifica le autorizzazioni appropriate e genera
SecurityExceptionse l'app non ne ha. Ad esempio, se provi ad avviare un servizio in primo piano di tipolocation, il sistema verifica che la tua app disponga già dell'autorizzazioneACCESS_COARSE_LOCATIONoACCESS_FINE_LOCATION. La documentazione relativa ai tipi di servizi in primo piano elenca i prerequisiti richiesti per ogni tipo di servizio in primo piano.
Lancia un servizio
Per avviare un servizio in primo piano, devi prima avviarlo come servizio ordinario (non in primo piano):
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);
Punti chiave sul codice
- Lo snippet di codice avvia un servizio. Tuttavia, il servizio non è ancora in esecuzione in primo piano. All'interno del servizio stesso, devi chiamare
ServiceCompat.startForeground()per promuovere il servizio a un servizio in primo piano.
Promuovi un servizio in primo piano
Una volta che un servizio è in esecuzione, devi chiamare ServiceCompat.startForeground() per richiedere che il servizio venga eseguito in primo piano. In genere, questo metodo viene chiamato nel metodo onStartCommand() del servizio.
ServiceCompat.startForeground() accetta i seguenti parametri:
- Il servizio.
- Un numero intero positivo che identifica in modo univoco la notifica del servizio nella barra di stato.
- L'oggetto
Notificationstesso. - I tipi di servizi in primo piano che identificano il lavoro svolto dal servizio
I tipi di servizi in primo piano che passi a startForeground()
tipi dichiarati nel manifest, a seconda del caso d'uso
specifico. In seguito, se devi aggiungere altri tipi di servizi, puoi chiamare di nuovo startForeground().
Ad esempio, supponiamo che un'app di fitness esegua un servizio di monitoraggio della corsa che ha sempre bisogno delle informazioni di location, ma potrebbe o meno dover riprodurre contenuti multimediali. Dovresti dichiarare sia location sia mediaPlayback nel manifest. Se un utente inizia una corsa e vuole solo che la sua posizione venga monitorata, la tua app deve chiamare startForeground() e passare solo l'autorizzazione ACCESS_FINE_LOCATION. Poi, se l'utente vuole iniziare a riprodurre l'audio, chiama di nuovo startForeground() e passa la combinazione bit per bit di tutti i tipi di servizi in primo piano (in questo caso, ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).
L'esempio seguente mostra il codice che un servizio della fotocamera utilizzerebbe per passare a un servizio in primo piano:
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 = PermissionChecker.checkSelfPermission(this, Manifest.permission.CAMERA) if (cameraPermission != PermissionChecker.PERMISSION_GRANTED) { // 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) } // ... } } //... }
Punti chiave sul codice
- L'app ha già dichiarato nel file manifest che richiede l'autorizzazione
CAMERA. Tuttavia, l'app deve anche verificare in fase di runtime che l'utente abbia concesso l'autorizzazione. Se l'app non dispone effettivamente delle autorizzazioni corrette, deve informare l'utente del problema. - Sono stati introdotti diversi tipi di servizi in primo piano con diverse versioni della piattaforma Android. Questo codice controlla la versione di Android su cui è in esecuzione e richiede le autorizzazioni appropriate.
- Il codice verifica la presenza di
ForegroundServiceStartNotAllowedExceptionnel caso in cui stia tentando di avviare un servizio in primo piano in una situazione non consentita (ad esempio, se sta tentando di promuovere il servizio in primo piano mentre l'app è in background).