Le lancement d'un service de premier plan à partir de votre application se fait en deux étapes. Tout d'abord, vous devez démarrer le service en appelant context.startForegroundService()
. Ensuite, demandez au service d'appeler ServiceCompat.startForeground()
pour s'auto-promouvoir en service de premier plan.
Prérequis
Selon le niveau d'API ciblé par votre application, certaines restrictions s'appliquent au moment où une application peut lancer un service de premier plan.
Les applications qui ciblent Android 12 (niveau d'API 31) ou une version ultérieure ne sont pas autorisées à démarrer un service de premier plan lorsque l'application est en arrière-plan, sauf dans quelques cas spécifiques. Pour en savoir plus et connaître les exceptions à cette règle, consultez la section 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 une exception
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 le type de service de premier plan liste les conditions préalables requises 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 (hors 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 ne s'exécute pas encore au premier plan. Dans le service lui-même, vous devez appeler
ServiceCompat.startForeground()
pour promouvoir le service en service de premier plan.
Mettre 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 appelez 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. - Type ou types de services de premier plan identifiant le travail effectué par le service
Les types de services de premier plan que vous transmettez à startForeground()
sont les 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 la course à pied qui a toujours besoin d'informations location
, mais qui peut ou non avoir besoin de lire des contenus multimédias. Vous devez déclarer à la fois location
et mediaPlayback
dans le fichier manifeste. Si un utilisateur commence à courir et souhaite simplement que sa position soit suivie, votre application doit appeler startForeground()
et ne transmettre que l'autorisation ACCESS_FINE_LOCATION
. Ensuite, si l'utilisateur souhaite commencer à lire de l'audio, appelez à nouveau startForeground()
et transmettez la combinaison par bits 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 d'appareil photo utiliserait pour s'auto-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 a 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 informer l'utilisateur du problème. - 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 vérifie
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 lorsque l'application est en arrière-plan).