Pour lancer un service de premier plan depuis votre application, vous devez d'abord démarrer le service en appelant context.startForegroundService()
. Ensuite, demandez au service d'appeler ServiceCompat.startForeground()
pour se promouvoir en service de premier plan.
Prérequis
Selon le niveau d'API ciblé par votre application, certaines restrictions s'appliquent au lancement d'un service de premier plan.
Les applications qui ciblent Android 12 (niveau d'API 31) ou version ultérieure ne sont pas autorisées à démarrer un service de premier plan lorsque l'application est en arrière-plan, à quelques exceptions près. Pour en savoir plus et connaître les exceptions à cette règle, consultez Restrictions concernant le démarrage d'un service de premier plan en arrière-plan.
Les applications qui ciblent Android 14 (niveau d'API 34) ou version ultérieure doivent demander les autorisations appropriées pour le type de service de premier plan. Lorsque l'application tente de promouvoir un service au premier plan, le système vérifie les autorisations appropriées et génère
SecurityException
si l'application en manque. Par exemple, si vous essayez de lancer un service de premier plan de typelocation
, le système vérifie que votre application dispose déjà de l'autorisationACCESS_COARSE_LOCATION
ouACCESS_FINE_LOCATION
. La documentation sur les types de services de premier plan liste les prérequis requis pour chaque type de service de premier plan.
Lancer un service
Pour lancer un service de premier plan, vous devez d'abord le lancer en tant que service ordinaire (non de premier plan) :
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);
Points clés concernant le code
- L'extrait de code lance un service. Toutefois, le service n'est pas encore en cours d'exécution au premier plan. Dans le service lui-même, vous devez appeler
ServiceCompat.startForeground()
pour promouvoir le service en tant que service de premier plan.
Promouvoir un service au premier plan
Une fois qu'un service est en cours d'exécution, vous devez appeler ServiceCompat.startForeground()
pour demander que le service s'exécute au premier plan. Normalement, vous appelleriez cette méthode dans la méthode onStartCommand()
du service.
ServiceCompat.startForeground()
utilise les paramètres suivants :
- Le service.
- Entier positif qui identifie de manière unique la notification du service dans la barre d'état.
- L'objet
Notification
lui-même. - Le ou les types de services de premier plan qui identifient le travail effectué par le service
Les types de services de premier plan que vous transmettez à startForeground()
doivent correspondre aux types déclarés dans le fichier manifeste, en fonction du cas d'utilisation spécifique. Ensuite, si vous devez ajouter d'autres types de services, vous pouvez appeler startForeground()
à nouveau.
Par exemple, supposons qu'une application de fitness exécute un service de suivi de course à pied qui a toujours besoin d'informations location
, mais qui peut ou non avoir besoin de lire des contenus multimédias. Vous devrez déclarer à la fois location
et mediaPlayback
dans le fichier manifeste. Si un utilisateur commence une course et souhaite simplement que sa position soit suivie, votre application doit appeler startForeground()
et transmettre uniquement l'autorisation ACCESS_FINE_LOCATION
. Ensuite, si l'utilisateur souhaite lancer la lecture audio, appelez à nouveau startForeground()
et transmettez la combinaison bit à bit de tous les types de services de premier plan (dans ce cas, ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK
).
L'exemple suivant montre le code qu'un service de caméras utiliserait pour se promouvoir en tant que service de premier plan :
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) } // ... } } //... }
Points clés concernant le code
- L'application a déjà déclaré dans le fichier manifeste qu'elle avait besoin de l'autorisation
CAMERA
. Toutefois, l'application doit également vérifier au moment de l'exécution que l'utilisateur a accordé cette autorisation. Si l'application ne dispose pas des autorisations appropriées, elle doit en informer l'utilisateur. - Différents types de services de premier plan ont été introduits avec différentes versions de la plate-forme Android. Ce code vérifie la version d'Android sur laquelle il s'exécute et demande les autorisations appropriées.
- Le code recherche
ForegroundServiceStartNotAllowedException
au cas où il tenterait de démarrer un service de premier plan dans une situation non autorisée (par exemple, s'il tente de promouvoir le service au premier plan alors que l'application est en arrière-plan).