Services de premier plan

Les services de premier plan effectuent des opérations qui peuvent être remarquées par l'utilisateur.

Les services de premier plan affichent une barre d'état de notification, pour informer les utilisateurs que l'application effectue une tâche au premier plan et consomme des ressources système.

Voici quelques exemples d'applications qui utilisent les services de premier plan:

  • Une application de lecteur de musique qui lit de la musique dans un service de premier plan. La notification peut afficher le titre en cours de lecture.
  • Une application de fitness qui enregistre la course à pied d'un utilisateur dans un service de premier plan, après de recevoir l'autorisation de l'utilisateur. La notification peut indiquer la distance que l'utilisateur a parcourus pendant la session de fitness en cours.

N'utilisez un service de premier plan que lorsque votre application doit effectuer une tâche visible par l'utilisateur, même lorsqu'il n'interagit pas directement avec l'application. Si l'importance de l'action est suffisamment faible pour que vous souhaitiez utiliser un notification de priorité minimale, créez un arrière-plan tâche.

Ce document décrit l'autorisation requise pour utiliser les services de premier plan, et comment démarrer un service de premier plan et le supprimer de l'arrière-plan. Il y a aussi décrit comment associer certains cas d'utilisation à des types de services de premier plan ; les restrictions d'accès qui s'appliquent lorsque vous démarrez un service de premier plan ; à partir d'une application qui s'exécute en arrière-plan.

L'utilisateur peut ignorer la notification par défaut

À partir d'Android 13 (niveau d'API 33), les utilisateurs peuvent ignorer la notification. associés à un service de premier plan par défaut. Pour ce faire, ils doivent balayer l'écran geste sur la notification. Habituellement, la notification n'est pas ignoré, sauf si le service de premier plan est arrêté ou supprimé au premier plan.

Si vous souhaitez que l'utilisateur ne puisse pas ignorer la notification, transmettez true dans le setOngoing() lorsque vous créez une notification avec Notification.Builder.

Services qui affichent une notification immédiatement

Si un service de premier plan possède au moins l'une des caractéristiques suivantes, système affiche la notification associée immédiatement après le démarrage du service, même sur les appareils équipés d'Android 12 ou version ultérieure:

Sur Android 13 (niveau d'API 33) ou version ultérieure, si l'utilisateur refuse l'accès autorisation de notification, il continue de voir des notifications liées aux services de premier plan Gestionnaire de tâches mais qu'ils ne s'affichent pas dans le panneau des notifications.

Déclarer les services de premier plan dans votre fichier manifeste

Dans le fichier manifeste de votre application, déclarez chacun des services de premier plan de votre application. avec un <service> . Pour chaque service, utilisez un Attribut android:foregroundServiceType pour déclarer le type de travail effectué par le service.

Par exemple, si votre application crée un service de premier plan qui lit de la musique, vous vous pouvez déclarer le service comme suit:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
  <application ...>

    <service
        android:name=".MyMediaPlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="false">
    </service>
  </application>
</manifest>

Si vos différents types s'appliquent à votre service, séparez-les à l'aide du caractère |. . Par exemple, un service qui utilise la caméra et le micro le déclarerait comme suit:

android:foregroundServiceType="camera|microphone"

Demander les autorisations du service de premier plan

Applications qui ciblent Android 9 (niveau d'API 28) ou version ultérieure et utilisent des services de premier plan n'avez pas besoin de demander FOREGROUND_SERVICE dans le fichier manifeste de l'application, comme indiqué dans l'extrait de code suivant. Il s'agit d'une erreur normale l'autorisation, de sorte que le système l'accorde automatiquement à l'application à l'origine de la demande.

De plus, si l'application cible le niveau d'API 34 ou supérieur, elle doit demander l'API le type d'autorisation approprié pour le type de tâche que le service de premier plan faire. Chaque type de service de premier plan possède un type d'autorisation correspondant. Par exemple, si une application lance service de premier plan qui utilise l'appareil photo, vous devez demander à la fois FOREGROUND_SERVICE et FOREGROUND_SERVICE_CAMERA autorisations. Ce sont toutes des autorisations normales, donc le système les accorde automatiquement s'ils sont répertoriés dans le fichier manifeste.

<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>

Conditions préalables pour le service de premier plan

À partir d'Android 14 (niveau d'API 34), lorsque vous lancez un service de premier plan, le système vérifie les conditions préalables spécifiques en fonction du type de service. Par exemple : Si vous essayez de lancer un service de premier plan de type location, le système vérifie pour vous assurer que votre application dispose déjà des autorisations ACCESS_COARSE_LOCATION ou Autorisation ACCESS_FINE_LOCATION. Si ce n'est pas le cas, le système génère SecurityException

Par conséquent, vous devez confirmer que les conditions préalables requises sont remplies avant de démarrer un service de premier plan. Le service de premier plan documentation liste les conditions préalables requises pour chaque type de service de premier plan.

Démarrer un service de premier plan

Avant de demander au système d'exécuter un service en tant que service de premier plan, le service lui-même:

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);

Dans le service, généralement dans onStartCommand(), vous pouvez demander que votre service s'exécute au premier plan. Pour ce faire, appelez ServiceCompat.startForeground() (disponible avec Androidx-core 1.12 ou version ultérieure). Cette méthode utilise les éléments suivants : paramètres:

Ces types peuvent constituer un sous-ensemble des types déclarés dans le fichier manifeste, selon le cas d'utilisation spécifique. Ensuite, si vous devez ajouter d'autres types de services, vous pouvez rappeler startForeground().

Par exemple, supposons qu'une application de fitness exécute un service de suivi de la course à pied qui a besoin des informations location, mais il peut ou non avoir besoin de lire des contenus multimédias. Toi doit déclarer à la fois location et mediaPlayback dans le fichier manifeste. Si un un utilisateur commence à courir et souhaite simplement suivre sa position, votre application doit appeler startForeground() et transmettez uniquement l'autorisation ACCESS_FINE_LOCATION. Ensuite, Si l'utilisateur souhaite commencer à lire l'audio, appelez de nouveau startForeground() et transmet la combinaison bit à bit de tous les types de services de premier plan (dans ce cas, ACCESS_FINE_LOCATION|FOREGROUND_SERVICE_MEDIA_PLAYBACK).

Voici un exemple qui lance un service de premier plan d'appareil photo:

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)
            }
            // ...
        }
    }

    //...
}

Supprimer un service du premier plan

Pour supprimer le service au premier plan, appelez stopForeground() Cette méthode utilise une valeur booléenne, qui indique s'il faut supprimer la barre d'état . Notez que le service continue de s'exécuter.

Si vous arrêtez le service alors qu'il s'exécute au premier plan, la notification est supprimé.

Gérer l'arrêt déclenché par l'utilisateur des applications exécutant des services de premier plan

En bas du panneau des notifications, un bouton indique
    le nombre d&#39;applications qui s&#39;exécutent actuellement en arrière-plan. Lorsque vous appuyez sur
    ce bouton, une boîte de dialogue contenant le nom des différentes applications s&#39;affiche. La
    Le bouton d&#39;arrêt se trouve à droite de chaque application
Figure 1. du gestionnaire de tâches sur les appareils équipés d'Android 13 ou version ultérieure.

À partir d'Android 13 (niveau d'API 33), les utilisateurs peuvent suivre un workflow depuis la panneau des notifications pour arrêter une application dont les services de premier plan sont en cours, quelle que soit la la version du SDK cible. Cette affordance, appelée Gestionnaire de tâches : affiche la liste des applications qui sont qui exécute actuellement un service de premier plan.

Cette liste est intitulée Applications actives. Un bouton Arrêter apparaît à côté de chaque application. La figure 1 illustre Workflow du gestionnaire de tâches sur un appareil qui exécute Android 13.

Lorsque l'utilisateur appuie sur le bouton Stop à côté de votre application dans la Gestionnaire des tâches, les actions suivantes se produisent:

  • Le système supprime votre application de la mémoire. Par conséquent, l'intégralité de votre application s'arrête, et pas seulement le service de premier plan en cours d'exécution.
  • Le système supprime la pile "Retour" d'activité de votre application.
  • La lecture des contenus multimédias s'arrête.
  • La notification associée au service de premier plan est supprimée.
  • Votre application est conservée dans l'historique.
  • Les jobs planifiés s'exécutent à l'heure prévue.
  • Les alarmes sonnent à l'heure ou à la fenêtre programmée.

Pour vérifier que votre application se comporte comme prévu pendant et après l'arrêt de votre exécutez la commande ADB suivante dans une fenêtre de terminal:

adb shell cmd activity stop-app PACKAGE_NAME

Exceptions

Le système prévoit plusieurs niveaux d'exemption pour certains types d'applications, décrit dans les sections suivantes.

Les exceptions sont imposées par application et non par processus. Si le système exempte un processus d'une application, tous les autres processus de cette application sont également exemptés.

Des exceptions d’apparaître dans le gestionnaire de tâches

Les applications suivantes peuvent exécuter un service de premier plan et ne pas apparaître dans le Gestionnaire de tâches:

  • Applications système
  • Applications de sécurité c'est-à-dire les applications qui ont Rôle ROLE_EMERGENCY
  • Appareils qui se trouvent dans mode démo

Exemption de la désactivation par les utilisateurs

Lorsque les types d'applications suivants exécutent un service de premier plan, elles apparaissent dans Gestionnaire des tâches, mais aucun bouton Arrêter ne s'affiche à côté nom de l'application pour que l'utilisateur puisse appuyer dessus:

Utiliser des API sur mesure plutôt que des services de premier plan

Dans de nombreux cas d'utilisation, il existe des API de plate-forme ou Jetpack que vous pouvez utiliser pour travailler pour lequel vous pourriez autrement utiliser un service de premier plan. S'il existe un API spécifique, il est presque toujours préférable de l'utiliser au lieu d'utiliser un premier plan Google Cloud. Les API sur mesure fournissent souvent des cas d'utilisation supplémentaires des capacités que vous auriez dû développer vous-même autrement. Par exemple : l' API Bubbles gère la logique d'UI complexe pour les applications de messagerie qui doivent implémenter des fonctionnalités de bulles de chat.

La documentation sur les types de services de premier plan répertorie de bonnes alternatives à l'utilisation à la place des services de premier plan.

Restrictions concernant le démarrage d'un service de premier plan en arrière-plan

Les applications qui ciblent Android 12 ou version ultérieure ne peuvent pas démarrer au premier plan services pendant que l'application s'exécute en arrière-plan, à l'exception de quelques cas d'utilisation. Si une application tente de démarrer un service de premier plan pendant que l'application s'exécute en arrière-plan, et au premier plan ne satisfasse pas l'un des cas exceptionnels, le système génère ForegroundServiceStartNotAllowedException

De plus, si une application souhaite lancer un service de premier plan qui a besoin les autorisations pendant l'utilisation (par exemple, capteur corporel, caméra, micro ou lieu autorisations), il ne peut pas créer le service lorsque l'application est exécutée en arrière-plan, même si l'application est concernée par l'une des exceptions au démarrage en arrière-plan de restrictions. Cela est expliqué dans la section Restrictions démarrent les services de premier plan qui doivent être utilisés autorisations.

Exemptions des restrictions de démarrage en arrière-plan

Dans les situations suivantes, votre application peut démarrer des services de premier plan même si votre application s'exécute en arrière-plan:

Restrictions concernant le démarrage des services de premier plan qui nécessitent des autorisations en cours d'utilisation

Sur Android 14 (niveau d'API 34) ou version ultérieure, vous devez connaître certaines situations spéciales. ou si vous démarrez un service de premier plan nécessitant des autorisations en cours d'utilisation.

Si votre application cible Android 14 ou une version ultérieure, le système d'exploitation lorsque vous créez un service de premier plan pour vous assurer que votre application dispose les autorisations appropriées pour ce type de service. Par exemple, lorsque vous créez un service de premier plan de type micro, le système d'exploitation de votre application pour vérifier qu'elle dispose RECORD_AUDIO l'autorisation. Si vous ne disposez pas de cette autorisation, le système génère une SecurityException

Cela peut poser problème pour les autorisations en cours d'utilisation. Si votre application dispose d'un alors qu'il est en cours d'utilisation, il ne dispose de cette autorisation que lorsqu'il se trouve dans au premier plan. Cela signifie que si votre application est exécutée en arrière-plan et tente de créer service de premier plan de type caméra, emplacement ou micro, le système détecte que votre application ne dispose pas actuellement des autorisations requises et qu'elle génère une erreur SecurityException

De même, si votre application est exécutée en arrière-plan et qu'elle crée qui a besoin de l'autorisation BODY_SENSORS_BACKGROUND, l'application ne dispose pas de cette autorisation pour le moment, et le système génère une exception. (Cela ne s'applique pas s'il s'agit d'un service de santé qui nécessite des autorisations différentes, comme ACTIVITY_RECOGNITION.) PermissionChecker.checkSelfPermission() n'empêche pas ce problème. Si votre application dispose d'une autorisation "En cours d'utilisation" il appelle checkSelfPermission() pour vérifier s'il dispose de cette autorisation, la méthode renvoie PERMISSION_GRANTED même si l'application est exécutée en arrière-plan. Lorsque renvoie PERMISSION_GRANTED, elle indique "votre application dispose de cette autorisation lorsque l'application est en cours d'utilisation."

Pour cette raison, si votre service de premier plan nécessite une autorisation en cours d'utilisation, vous doit appeler Context.startForegroundService() ou Context.bindService() tout en votre application présente une activité visible, sauf si le service est inclus dans l'un des des exemptions définies.

Exemptions des restrictions sur les autorisations d'utilisation

Dans certains cas, même si un service de premier plan est démarré alors que l'application courses en arrière-plan, il peut toujours accéder à votre position, des informations sur la caméra et le micro lorsque l'application s'exécute au premier plan. ("pendant l'utilisation").

Dans ces mêmes situations, si le service déclare type de service de premier plan de location et qui est démarré par une application qui contient le ACCESS_BACKGROUND_LOCATION l'autorisation, ce service peut accéder aux informations de localisation en permanence, même l'application s'exécute en arrière-plan.

Vous trouverez dans la liste suivante les situations suivantes:

  • Un composant système démarre le service.
  • Le service commence par interagir avec les widgets
  • Le service commence par interagir avec une notification.
  • Le service commence par PendingIntent envoyé depuis un une application différente et visible.
  • Le service commence par une application qui est une règle relative aux appareils manette qui s'exécute en mode propriétaire de l'appareil.
  • Le service commence par une application qui fournit le VoiceInteractionService.
  • Le service commence par une application Autorisation privilégiée START_ACTIVITIES_FROM_BACKGROUND.
Déterminer les services concernés dans votre application

Lorsque vous testez votre application, démarrez ses services de premier plan. Si un service démarré l'accès à la position, au micro et à l'appareil photo est limité, le message suivant apparaît dans Logcat:

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME