Chaque fois qu'une application s'exécute en arrière-plan, elle consomme une partie des ressources limitées de l'appareil, telles que la RAM. Cela peut nuire à l'expérience utilisateur, en particulier si l'utilisateur utilise une application qui utilise beaucoup de ressources, par exemple lorsqu'il joue à un jeu ou regarde une vidéo. Pour améliorer l'expérience utilisateur, Android 8.0 (niveau d'API 26) limite ce que les applications peuvent faire lorsqu'elles s'exécutent en arrière-plan. Ce document décrit les modifications apportées au système d'exploitation et explique comment mettre à jour votre application pour qu'elle fonctionne correctement avec les nouvelles limites.
Présentation
De nombreux services et applications Android peuvent s'exécuter simultanément. Par exemple, un utilisateur peut jouer à un jeu dans une fenêtre tout en naviguant sur le Web dans une autre fenêtre et utiliser une troisième application pour écouter de la musique. Plus les applications s'exécutent en même temps, plus la charge est élevée sur le système. Si d'autres applications ou services s'exécutent en arrière-plan, cela entraîne des charges supplémentaires sur le système, ce qui peut nuire à l'expérience utilisateur. Par exemple, l'application musicale peut être soudainement arrêtée.
Pour réduire le risque de ces problèmes, Android 8.0 limite les actions autorisées par les applications lorsque les utilisateurs n'interagissent pas directement avec elles. Les applications sont limitées de deux manières:
Limites applicables aux services d'arrière-plan: Lorsqu'une application est inactive, son utilisation des services d'arrière-plan est limitée. Cela ne s'applique pas aux services de premier plan, qui sont plus visibles pour l'utilisateur.
Limites des diffusions: avec des exceptions limitées, les applications ne peuvent pas utiliser leur fichier manifeste pour s'inscrire aux diffusions implicites. Ils peuvent toujours s'inscrire à ces diffusions au moment de l'exécution et utiliser le fichier manifeste pour s'inscrire aux annonces explicites et aux annonces ciblant spécifiquement leur application.
Dans la plupart des cas, les applications peuvent contourner ces limites à l'aide de tâches JobScheduler
. Cette approche permet à une application de s'organiser lorsqu'elle n'est pas activement en cours d'exécution, mais elle permet au système de planifier ces tâches sans affecter l'expérience utilisateur. Android 8.0 propose plusieurs améliorations à JobScheduler
qui facilitent le remplacement des services et des broadcast receivers par des tâches planifiées. Pour en savoir plus, consultez la section Améliorations apportées à JobScheduler.
Limites applicables aux services d'arrière-plan
Les services exécutés en arrière-plan peuvent consommer des ressources de l'appareil, ce qui peut nuire à l'expérience utilisateur. Pour atténuer ce problème, le système applique un certain nombre de limites aux services.
Le système fait la distinction entre les applications au premier plan et celles en arrière-plan. (La définition de l'arrière-plan aux fins des limites de service est différente de la définition utilisée par la gestion de la mémoire. Une application peut se trouver en arrière-plan pour ce qui est de la gestion de la mémoire, mais au premier plan en ce qui concerne sa capacité à lancer des services.) Une application est considérée comme exécutée au premier plan si l'une des conditions suivantes est remplie:
- Elle présente une activité visible, qu'elle soit lancée ou mise en veille.
- Il dispose d'un service de premier plan.
- Une autre application de premier plan est connectée à l'application, soit en l'associant à l'un de ses services, soit en utilisant l'un de ses fournisseurs de contenu. Par exemple, l'application se trouve au premier plan si une autre application se lie à :
- Éditeur de mode de saisie
- Service de fonds d'écran
- Outil d'écoute des notifications
- Service d'appels ou de messages
Si aucune de ces conditions n'est remplie, l'application est considérée comme étant en arrière-plan.
Lorsqu'une application est au premier plan, elle peut créer et exécuter librement des services de premier plan et d'arrière-plan. Lorsqu'une application passe en arrière-plan, elle dispose d'une fenêtre de plusieurs minutes pendant laquelle elle est toujours autorisée à créer et à utiliser des services. À la fin de cette fenêtre, l'application est considérée comme inactive. À ce stade, le système arrête les services d'arrière-plan de l'application, comme si l'application avait appelé les méthodes Service.stopSelf()
des services.
Dans certains cas, une application en arrière-plan est placée sur une liste d'autorisation temporaire pendant plusieurs minutes. Lorsqu'une application figure sur la liste d'autorisation, elle peut lancer des services sans s'y limiter, et ses services d'arrière-plan sont autorisés à s'exécuter. Une application est placée sur la liste d'autorisation lorsqu'elle gère une tâche visible par l'utilisateur, par exemple:
- Le traitement d'un message Firebase Cloud Messaging (FCM) à priorité élevée.
- Réception d'une annonce, par exemple un SMS/MMS
- Exécuter un
PendingIntent
à partir d'une notification. - Lancer un
VpnService
avant que l'application VPN ne passe au premier plan
Dans de nombreux cas, votre application peut remplacer les services d'arrière-plan par des tâches JobScheduler
.
Par exemple, CoolPhotoApp doit vérifier si l'utilisateur a reçu des photos partagées d'amis, même si l'application ne s'exécute pas au premier plan. Auparavant, l'application utilisait un service d'arrière-plan qui vérifie son espace de stockage cloud. Pour migrer vers Android 8.0 (niveau d'API 26), le développeur remplace le service d'arrière-plan par une tâche planifiée, lancée régulièrement, interroge le serveur, puis se ferme.
Avant Android 8.0, la méthode habituelle pour créer un service de premier plan consistait à créer un service d'arrière-plan, puis à le promouvoir au premier plan.
Avec Android 8.0, une complication se produit : le système n'autorise pas une application en arrière-plan à créer un service d'arrière-plan. C'est pourquoi Android 8.0 introduit la nouvelle méthode startForegroundService()
pour démarrer un nouveau service au premier plan. Une fois le service créé, l'application dispose de cinq secondes pour appeler la méthode [startForeground()
](/reference/android/app/Service#startForeground(int, android.app.Notification) du service afin d'afficher la notification du nouveau service visible par l'utilisateur. Si l'application n'appelle pas startForeground()
dans le délai imparti, le système arrête le service et déclare l'application comme ANR.
Limites de diffusion
Si une application s'inscrit pour recevoir des annonces, le récepteur de l'application consomme des ressources chaque fois que l'annonce est envoyée. Cela peut causer des problèmes si trop d'applications s'enregistrent pour recevoir des annonces en fonction des événements système. Un événement système qui déclenche une diffusion peut entraîner la consommation rapide de ressources par toutes ces applications, ce qui nuit à l'expérience utilisateur. Pour atténuer ce problème, Android 7.0 (niveau d'API 24) a appliqué des limites aux diffusions, comme décrit dans la section Optimisation en arrière-plan. Android 8.0 (niveau d'API 26) rend ces limites plus strictes.
- Les applications qui ciblent Android 8.0 ou une version ultérieure ne peuvent plus enregistrer de broadcast receivers pour les annonces implicites dans leur fichier manifeste, sauf si la diffusion est limitée à cette application spécifiquement. Une diffusion implicite est une diffusion qui ne cible pas un composant spécifique au sein d'une application. Par exemple,
ACTION_PACKAGE_REPLACED
est envoyé à tous les écouteurs enregistrés dans toutes les applications, ce qui leur indique qu'un package de l'appareil a été remplacé. La diffusion étant implicite, elle ne sera pas envoyée aux destinataires enregistrés dans le fichier manifeste dans les applications qui ciblent Android 8.0 ou version ultérieure.ACTION_MY_PACKAGE_REPLACED
est également une diffusion implicite, mais puisqu'il n'est envoyé qu'à l'application dont le package a été remplacé, il sera distribué aux destinataires enregistrés dans le fichier manifeste. - Les applications peuvent continuer à s'inscrire pour diffuser des annonces explicites dans leurs fichiers manifestes.
- Les applications peuvent utiliser
Context.registerReceiver()
au moment de l'exécution afin d'enregistrer un récepteur pour toute diffusion, implicite ou explicite. - Les annonces qui nécessitent une autorisation de signature sont exemptées de cette restriction, car elles ne sont envoyées qu'aux applications signées avec le même certificat, et non à toutes les applications de l'appareil.
Dans de nombreux cas, les applications qui se sont précédemment inscrites pour une diffusion implicite peuvent obtenir une fonctionnalité similaire en utilisant une tâche JobScheduler
.
Par exemple, une application de réseau social de photos peut avoir besoin d'effectuer un nettoyage de ses données de temps en temps et préférer le faire lorsque l'appareil est connecté à un chargeur.
Auparavant, l'application enregistrait un récepteur pour ACTION_POWER_CONNECTED
dans son fichier manifeste. Lorsque l'application recevait cette annonce, elle vérifiait si un nettoyage était nécessaire. Pour migrer vers Android 8.0 ou version ultérieure, l'application supprime ce récepteur de son fichier manifeste. À la place, l'application planifie une tâche de nettoyage qui s'exécute lorsque l'appareil est inactif et en charge.
Guide de migration
Par défaut, ces modifications n'affectent que les applications qui ciblent Android 8.0 (niveau d'API 26) ou version ultérieure. Toutefois, les utilisateurs peuvent activer ces restrictions pour n'importe quelle application à partir de l'écran Settings (Paramètres), même si l'application cible un niveau d'API inférieur à 26. Vous devrez peut-être mettre à jour votre application pour respecter les nouvelles limites.
Vérifiez comment votre application utilise les services. Si votre application repose sur des services qui s'exécutent en arrière-plan lorsqu'elle est inactive, vous devez les remplacer. Voici les solutions possibles:
- Si votre application doit créer un service de premier plan lorsqu'elle est en arrière-plan, utilisez la méthode
startForegroundService()
au lieu destartService()
. - Si le service est perceptible par l'utilisateur, faites-en un service de premier plan. Par exemple, un service de lecture audio doit toujours être un service de premier plan.
Créez le service à l'aide de la méthode
startForegroundService()
au lieu destartService()
. - Trouvez un moyen de dupliquer la fonctionnalité du service avec une tâche planifiée. Si le service ne fait pas quelque chose immédiatement visible pour l'utilisateur, vous devriez généralement pouvoir utiliser une tâche planifiée à la place.
- Utilisez FCM pour activer de manière sélective votre application lorsque des événements réseau se produisent, plutôt que d'interroger en arrière-plan.
- Différez les tâches en arrière-plan jusqu'à ce que l'application soit naturellement exécutée au premier plan.
Examinez les broadcast receivers définis dans le fichier manifeste de votre application. Si votre fichier manifeste déclare un récepteur pour une diffusion implicite affectée, vous devez le remplacer. Voici les solutions possibles:
- Créez le récepteur au moment de l'exécution en appelant
Context.registerReceiver()
au lieu de le déclarer dans le fichier manifeste. - Utilisez une tâche planifiée pour vérifier la condition qui aurait déclenché la diffusion implicite.