ANR

Lorsque le thread UI d'une application Android est bloqué trop longtemps, une erreur ANR (« L'application ne répond pas ») se déclenche. Android Vitals suit et signale les métriques ANR dans la Google Play Console pour vous aider à surveiller la stabilité et la réactivité de votre application sur tous les appareils.

Métriques et seuils Android Vitals

Android Vitals vous permet de surveiller et d'améliorer le taux d'erreurs ANR de votre application. Android Vitals mesure plusieurs taux d'erreurs ANR :

  • Taux d'erreurs ANR : pourcentage d'utilisateurs actifs par jour ayant subi un type d'erreur ANR.
  • Taux d'erreurs ANR perçues par l'utilisateur : pourcentage d'utilisateurs actifs par jour ayant subi au moins une erreur ANR perçue par l'utilisateur. Actuellement, seules les erreurs ANR de type Input dispatching timed out sont considérées comme étant repérées par l'utilisateur.
  • Taux d'erreurs ANR multiples : pourcentage de vos utilisateurs actifs par jour ayant subi au moins deux erreurs ANR.

Un utilisateur actif par jour est un utilisateur unique qui se sert de votre application un seul jour sur un seul appareil, avec éventuellement plusieurs sessions. Si un utilisateur se sert de votre application sur plusieurs appareils au cours d'une même journée, chaque appareil sera comptabilisé dans le nombre d'utilisateurs actifs pour ce jour-là.

Le taux d'erreurs ANR perçues par l'utilisateur est une statistique principale Android Vitals. Il affecte donc la visibilité de votre application sur Google Play. Cette métrique est importante, car les erreurs ANR comptabilisées se produisent toujours lorsque l'utilisateur interagit avec l'appli, ce qui entraîne le plus de perturbations.

Play a défini deux seuils de comportement insatisfaisant pour cette métrique :

  • Seuil de comportement insatisfaisant en général : au moins 0,47 % des utilisateurs actifs par jour subissent une erreur ANR repérée par l'utilisateur sur tous les modèles d'appareils.
  • Seuil de comportement insatisfaisant par appareil : au moins 8% des utilisateurs actifs par jour subissent une erreur ANR repérée par l'utilisateur sur un même modèle d'appareil.

Si votre application dépasse le seuil général de comportement insatisfaisant, elle risque d'être moins visible sur tous les appareils. Si elle dépasse le seuil de comportement insatisfaisant par appareil, elle risque d'être moins visible sur le type d'appareil en question et d'afficher un avertissement dans votre fiche Play Store.

Android Vitals peut vous envoyer des alertes via la Play Console lorsque votre application subit un nombre excessif d'erreurs ANR.

Pour savoir comment Google Play collecte les données Android Vitals, consultez la documentation de la Play Console.

Détecter le problème

Si l'application est exécutée au premier plan lorsqu'une erreur ANR se produit, le système affiche une boîte de dialogue, comme illustré dans la figure 1. La boîte de dialogue ANR permet à l'utilisateur de forcer l'arrêt de l'application.

Une boîte de dialogue ANR s'affiche à l'intention de l'utilisateur.
Figure 1. Boîte de dialogue ANR affichée

Les ANR posent problème, car le thread principal de l'application, responsable de la mise à jour de l'UI, ne peut pas traiter les événements d'entrée utilisateur ni dessiner, ce qui génère de la frustration pour l'utilisateur. Pour en savoir plus sur le thread principal de l'application, consultez Présentation des processus et des threads.

Une erreur ANR se déclenche pour votre application lorsque l'une des conditions suivantes se produit :

  • Délai d'envoi des entrées dépassé : si votre application n'a pas répondu à une entrée (comme un appui sur une touche ou un événement tactile sur l'écran) dans les cinq secondes.
  • Exécution du service : si un service déclaré par votre application ne peut pas terminer l'exécution de Service.onCreate et Service.onStartCommand ou Service.onBind en quelques secondes.
  • Service.startForeground non appelé : si votre application utilise Context.startForegroundService pour démarrer un nouveau service au premier plan, mais que le service n'appelle pas startForeground dans les cinq secondes.
  • Diffusion de l'intent : si l'exécution d'un BroadcastReceiver n'est pas terminée dans un délai donné. Si l'application présente une activité au premier plan, ce délai est de 10 secondes.
  • Interactions JobScheduler : si un JobService ne renvoie pas une valeur de JobService.onStartJob ou JobService.onStopJob dans les secondes qui suivent, ou si une tâche lancée par l'utilisateur démarre et que votre application n'appelle pas JobService.setNotification dans les quelques secondes suivant l'appel de JobService.onStartJob. Pour les applications ciblant Android 13 et les versions antérieures, les erreurs ANR sont silencieuses et ne sont pas signalées à l'application. Pour les applications ciblant Android 14 et versions ultérieures, les erreurs ANR sont explicites et sont signalées à l'application.

En plus d'Android Vitals, vous pouvez utiliser d'autres outils pour détecter les erreurs ANR sur le terrain. Notez toutefois que les outils tiers ne peuvent pas signaler les ANR sur Android 10 (niveau d'API 29) et versions antérieures.

Diagnostiquer les erreurs ANR

Voici quelques tendances courantes à prendre en compte lors du diagnostic des ANR :

  • L'application effectue des opérations lentes impliquant des E/S sur le thread principal.
  • L'application effectue un calcul long sur le thread principal.
  • Le thread principal effectue un appel de liaison synchrone vers un autre processus, et le retour de cet autre processus prend beaucoup de temps.
  • Le thread principal est bloqué en attendant un blocage synchronisé pour une longue opération qui se produit sur un autre thread.
  • Le thread principal se trouve dans un interblocage avec un autre thread, soit au cours de votre processus, soit via un appel de liaison. Le thread principal n'attend pas que l'opération longue se termine. Il se trouve dans une situation d'interblocage.

Les techniques suivantes peuvent vous aider à déterminer la cause de vos erreurs ANR.

HealthStats

HealthStats fournit des métriques sur l'état d'une application en capturant le temps système et utilisateur total, le temps CPU, le réseau, les métriques radio, le temps d'activation/de désactivation de l'écran et les alarmes de réveil. Cela peut vous aider à mesurer l'utilisation globale du processeur et la décharge de la batterie.

Déboguer

Debug vous permet d'inspecter les applications Android pendant le développement, y compris le traçage et le nombre d'allocations pour identifier les à-coups et la latence dans les applis. Vous pouvez également utiliser Debug pour obtenir des compteurs d'exécution et de mémoire native, ainsi que des métriques de mémoire qui peuvent vous aider à identifier l'espace mémoire utilisé d'un processus particulier.

ApplicationExitInfo

ApplicationExitInfo est disponible sur Android 11 (niveau d'API 30) ou version ultérieure et fournit des informations sur le motif de fermeture d'une application. Cela inclut les erreurs ANR, une mémoire insuffisante, les plantages d'application, l'utilisation excessive du processeur, les interruptions utilisateur, les interruptions système ou les modifications des autorisations d'exécution.

Mode strict

StrictMode vous aide à détecter les opérations d'E/S accidentelles sur le thread principal pendant le développement de votre application. Vous pouvez utiliser StrictMode au niveau de l'application ou de l'activité.

Activer les boîtes de dialogue ANR en arrière-plan

Android affiche des boîtes de dialogue ANR pour les applications qui mettent trop de temps à traiter le message de diffusion uniquement si l'option Afficher toutes les erreurs ANR est activée dans les Options pour les développeurs de l'appareil. Pour cette raison, les boîtes de dialogue ANR en arrière-plan ne sont pas toujours présentées à l'utilisateur, même lorsque l'application rencontre des problèmes de performances.

Profiler les traces du processeur et du système

Utilisez le profileur de processeur Android Studio pour enregistrer les traces système et l'activité du processeur pendant l'exécution de votre jeu. L'inspection du thread Activity principal, ainsi que des threads de rendu, audio et de travail de votre moteur de jeu, vous aide à repérer les frames longs, les chargements d'assets synchrones et les conflits de threads avant qu'ils ne déclenchent une erreur ANR.

Récupérer un fichier de traces

Android stocke les informations de trace en cas d'erreur ANR. Pour les versions d'Android plus anciennes, un seul fichier /data/anr/traces.txt est installé sur l'appareil. Dans les versions d'Android plus récentes, il existe plusieurs fichiers /data/anr/anr_*. Vous pouvez accéder aux traces ANR d'un appareil ou d'un émulateur en utilisant Android Debug Bridge (adb) en tant que racine :

adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>

Vous pouvez générer un rapport de bug à partir d'un appareil physique à l'aide de l'option "Créer un rapport de bug" du développeur sur l'appareil ou de la commande adb bugreport sur votre ordinateur de développement. Pour en savoir plus, consultez Capturer et lire les rapports de bug.

Résoudre les problèmes

Une fois que vous avez identifié le problème, vous pouvez utiliser les conseils de cette section pour le résoudre.

Lenteur du code dans le thread principal

Identifiez les emplacements de votre code où le thread principal de l'application est occupé pendant plus de cinq secondes. Recherchez les cas d'utilisation suspects dans votre jeu et essayez de reproduire l'erreur ANR.

Dans les jeux, les blocages du thread principal se produisent généralement lorsque la décompression synchrone des éléments, la compilation des nuanceurs ou l'initialisation de l'état du jeu s'exécutent sur le thread principal Android Activity (par exemple, dans onCreate, onResume ou les rappels JNI appelés depuis le thread UI). Déplacez l'exécution de la boucle de jeu, le traitement des éléments et l'initialisation de la scène vers des threads de moteur, de rendu ou de travail en arrière-plan dédiés, afin que le thread principal reste libre de traiter les événements d'entrée et de cycle de vie.

E/S sur le thread principal

L'exécution d'opérations d'E/S sur le thread principal est une cause fréquente de lenteur, ce qui peut entraîner des erreurs ANR.

Déplacez toutes les lectures de bundles d'assets, la sérialisation des jeux enregistrés, les accès SharedPreferences et les requêtes réseau du thread Activity principal vers des threads de travail en arrière-plan afin que la latence du stockage ou du réseau ne puisse pas bloquer la distribution des entrées.

Interblocages

Un interblocage se produit lorsqu'un thread passe à l'état d'attente, car une ressource requise est détenue par un autre thread, qui attend également une ressource détenue par le premier thread. Si le thread principal de l'application se trouve dans cette situation, il est probable que des erreurs ANR se produisent.

Dans les jeux, les blocages et les conflits de verrouillage se produisent fréquemment entre le thread Activity principal d'Android (qui gère le cycle de vie, la surface ou les rappels d'entrée) et les threads de rendu, de logique ou audio C ou C++ natifs. Évitez les attentes synchrones sur le thread principal pour les verrous du moteur natif, et utilisez un ordre de verrouillage cohérent ou des files d'attente de messages sans verrouillage lors de la communication entre les threads JNI et du moteur.

Les interblocages sont un phénomène bien étudié en informatique. Il existe des algorithmes de prévention des interblocages que vous pouvez utiliser pour éviter ce problème.

Pour en savoir plus, consultez les articles sur l'interblocage et la prévention des interblocages sur Wikipédia.

Broadcast receivers lents

Les applications peuvent répondre aux messages de diffusion, par exemple en activant ou en désactivant le mode Avion, ou en cas de changement d'état de la connectivité, à l'aide de broadcast receivers. Une erreur ANR se produit lorsqu'une application prend trop de temps pour traiter le message de diffusion.

Une erreur ANR se produit dans les cas suivants :

  • Un broadcast receiver n'a pas fini d'exécuter sa méthode onReceive dans un délai considérable.
  • Un broadcast receiver appelle goAsync et n'appelle pas finish sur l'objet PendingResult.

Votre application ne doit effectuer des opérations courtes que dans la méthode onReceive d'un BroadcastReceiver. Toutefois, si votre application nécessite un traitement plus complexe à la suite d'une annonce, vous devez reporter la tâche vers un thread de travail en arrière-plan si elle ne doit pas prendre plus de quelques secondes, ou vers WorkManager si elle doit prendre plus de quelques secondes.

GameActivity

La bibliothèque GameActivity a réduit le nombre d'erreurs ANR dans les études de cas de jeux et d'applications écrits en C ou C++. Si vous remplacez votre activité native existante par GameActivity, vous pouvez réduire le blocage des threads UI et empêcher certaines erreurs ANR.

Si vous créez votre jeu avec Unity, consultez Déboguer les erreurs ANR pour les jeux Unity, Erreurs ANR courantes dans les jeux Unity et Symboliser les plantages Android et les erreurs ANR pour les jeux Unity.

Pour en savoir plus sur les erreurs ANR, consultez Garder une application responsive. Pour en savoir plus sur les threads, consultez Améliorer les performances grâce à l'exécution de threads.