Restrictions système concernant les tâches en arrière-plan

Les processus en arrière-plan peuvent utiliser beaucoup de mémoire et de batterie. Par exemple, une diffusion implicite peut démarrer de nombreux processus en arrière-plan qui se sont inscrits pour l'écouter, même si ces processus n'effectuent pas beaucoup de travail. Cela peut avoir un impact important sur les performances des appareils et l'expérience utilisateur.

Pour éviter les restrictions système, assurez-vous d'utiliser l'API appropriée pour votre tâche en arrière-plan. La documentation de la présentation des tâches en arrière-plan vous aide à choisir l'API adaptée à vos besoins.

Restrictions initiées par l'utilisateur

Si une application présente certains des comportements insatisfaisants décrits dans Android Vitals, le système invite l'utilisateur à restreindre l'accès de cette application aux ressources système.

Si le système remarque qu'une application consomme des ressources excessives, il en informe l'utilisateur et lui donne la possibilité de limiter les actions de l'application. Cette notification peut apparaître dans les cas suivants :

  1. Nombre excessif de wakelocks: 1 wakelock partiel retenu pendant une heure lorsque l'écran est éteint
  2. Nombre excessif de services d'arrière-plan: si l'application cible des niveaux d'API inférieurs à 26 et comporte un nombre excessif de services d'arrière-plan

Les restrictions précises imposées sont déterminées par le fabricant de l'appareil. Par exemple, sur les versions AOSP, les applications dont l'accès est limité ne peuvent pas exécuter de tâches, déclencher d'alarmes ni utiliser le réseau, sauf lorsque l'application est exécutée au premier plan.

Restrictions concernant la réception d'annonces d'activité réseau

Les applications ne reçoivent pas d'annonces CONNECTIVITY_ACTION si elles s'inscrivent pour les recevoir dans leur fichier manifeste, et les processus qui en dépendent ne démarreront pas. Cela peut poser un problème pour les applications qui souhaitent écouter les modifications du réseau ou effectuer des activités réseau groupées lorsque l'appareil se connecte à un réseau illimité. Il existe déjà plusieurs solutions pour contourner cette restriction dans le framework Android, mais choisir la bonne dépend des objectifs que vous souhaitez obtenir avec votre application.

Planifier des tâches sur des connexions non facturées à l'usage

Lorsque vous créez un WorkRequest, ajoutez un Constraint NetworkType.UNMETERED.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

Lorsque les conditions de votre travail sont remplies, votre application reçoit un rappel pour exécuter la méthode doWork() dans la classe Worker spécifiée.

Surveiller la connectivité réseau pendant l'exécution de l'application

Les applications en cours d'exécution peuvent toujours écouter CONNECTIVITY_CHANGE avec un BroadcastReceiver enregistré. Cependant, l'API ConnectivityManager fournit une méthode plus robuste pour demander un rappel uniquement lorsque les conditions réseau spécifiées sont remplies.

Les objets NetworkRequest définissent les paramètres du rappel réseau en termes de NetworkCapabilities. Vous créez des objets NetworkRequest avec la classe NetworkRequest.Builder. registerNetworkCallback transmet ensuite l'objet NetworkRequest au système. Lorsque les conditions du réseau sont remplies, l'application reçoit un rappel pour exécuter la méthode onAvailable() définie dans sa classe ConnectivityManager.NetworkCallback.

L'application continue de recevoir des rappels jusqu'à ce qu'elle se ferme ou qu'elle appelle unregisterNetworkCallback().

Restrictions concernant la réception d'annonces images et vidéos

Les applications ne peuvent pas envoyer ni recevoir de diffusions ACTION_NEW_PICTURE ou ACTION_NEW_VIDEO. Cette restriction permet de réduire les performances et l'expérience utilisateur lorsque plusieurs applications doivent être activées pour traiter une nouvelle image ou vidéo.

Déterminer quelles autorités de contenu ont déclenché une action

WorkerParameters permet à votre application de recevoir des informations utiles sur les autorités de contenu et les URI qui ont déclenché la tâche:

List<Uri> getTriggeredContentUris()

Renvoie une liste d'URI qui ont déclenché la tâche. Ce champ est vide si aucun URI n'a déclenché la tâche (par exemple, si la tâche a été déclenchée en raison d'un délai ou pour une autre raison) ou si le nombre d'URI modifiés est supérieur à 50.

List<String> getTriggeredContentAuthorities()

Affiche une liste de chaînes d'autorités de contenu qui ont déclenché la tâche. Si la liste renvoyée n'est pas vide, utilisez getTriggeredContentUris() pour récupérer les détails des URI modifiés.

L'exemple de code suivant ignore la méthode CoroutineWorker.doWork() et enregistre les autorités de contenu et les URI qui ont déclenché la tâche:

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

Tester l'application en vertu de restrictions du système

Optimiser vos applications pour qu'elles s'exécutent sur des appareils ou dans des conditions limitées peut améliorer les performances et l'expérience utilisateur. La suppression des dépendances sur les services d'arrière-plan et les broadcast receivers implicites enregistrés dans le fichier manifeste peut aider votre application à mieux fonctionner sur ces appareils. Nous vous recommandons d'optimiser votre application pour qu'elle s'exécute sans utiliser complètement ces processus en arrière-plan.

Certaines commandes Android Debug Bridge (ADB) supplémentaires peuvent vous aider à tester le comportement de l'application en désactivant ces processus en arrière-plan:

  • Pour simuler des conditions dans lesquelles les diffusions implicites et les services d'arrière-plan ne sont pas disponibles, saisissez la commande suivante:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • Pour réactiver les diffusions implicites et les services d'arrière-plan, saisissez la commande suivante:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

Optimisez encore votre application

Pour découvrir d'autres façons d'optimiser le comportement de vos tâches en arrière-plan, consultez la documentation Optimiser l'utilisation de la batterie pour les API de planification des tâches.