ANR (Application Not Responding) est une notification système Android qui apparaît lorsqu'une application cesse de répondre aux entrées utilisateur pendant plus de 5 secondes. Selon Android Developers, la cause principale est les opérations longues sur le thread principal qui bloquent le traitement des touches et le rendu de l'interface. Comprendre les mécanismes d'ANR est essentiel pour tout développeur Android afin de créer des applications réactives.
Points clés
ANR (Application Not Responding) est une boîte de dialogue du système d'exploitation Android qui apparaît lorsqu'une application cesse de répondre aux entrées utilisateur. Le système suit le temps de traitement des événements via InputDispatcher : si un toucher ou une pression de bouton n'est pas traité dans les 5 secondes, Android affiche une boîte de dialogue proposant de fermer ou d'attendre l'application.
Le mécanisme ANR protège l'expérience utilisateur des applications figées. Android ne permet pas à une application de bloquer tout le système — contrairement aux systèmes d'exploitation de bureau, la plateforme mobile limite de force le temps de traitement des événements. BroadcastReceiver a une limite de 10 secondes, et un service au premier plan a 20 secondes.
L'ANR N'est PAS une exception dans le code — c'est un mécanisme système au niveau des processus Linux. Android envoie un signal SIGQUIT au processus, après quoi le système sauvegarde la pile d'appels de tous les threads dans le fichier traces.txt. Le développeur ne reçoit pas l'ANR comme une exception catch, mais comme un rapport après le redémarrage de l'application. Sur Android 11+, l'API ApplicationExitInfo permet d'obtenir programmatiquement la raison de la terminaison du processus, y compris l'ANR — cela simplifie la collecte de statistiques sans analyse manuelle de traces.txt.
Cinq catégories d'opérations mènent systématiquement à l'ANR dans les applications Android. Chacune d'elles bloque le thread principal, empêchant le système de traiter les événements d'entrée et le redessinage de l'écran.
Les requêtes HTTP synchrones exécutées sur le thread UI sont la cause la plus fréquente d'ANR chez les développeurs débutants. Même une requête rapide à un serveur peut prendre 1 à 3 secondes, et avec une mauvaise connexion — 30 secondes ou plus. Android interdit explicitement les opérations réseau sur le thread principal à partir de l'API 11, en lançant NetworkOnMainThreadException.
Utilisez Coroutines ou RxJava pour les appels asynchrones. Les coroutines avec le répartiteur Dispatchers.IO exécutent la requête dans un thread d'arrière-plan et transmettent le résultat au thread principal via Dispatchers.Main. Cela élimine complètement le blocage du thread UI par les opérations réseau.
fun fetchUserData() {
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.IO) {
api.getUserData() // opération en arrière-plan
}
updateUI(result) // résultat sur le thread principal
}
}
Traiter de grands tableaux de données, analyser du JSON ou XML, travailler avec des bitmaps directement sur le thread principal — la deuxième cause la plus fréquente d'ANR. Même 300 millisecondes de travail continu du thread UI sans retour à la boucle d'événements provoquent un retard notable du rendu, et le seuil de 5 secondes est enregistré comme ANR.
WorkManager et les services d'arrière-plan sont conçus pour déplacer les calculs lourds hors du thread principal. Utilisez AsyncTask (obsolète), ListenableFuture ou Kotlin Flow pour transmettre les données par morceaux sans bloquer l'UI.
Un Deadlock se produit lorsque deux threads détiennent des verrous et s'attendent mutuellement. Si l'un des threads est le thread principal, le système enregistre l'ANR exactement après 5 secondes. Thread.join(), CountDownLatch.await() et les blocs synchronized appelés depuis le thread UI comportent un risque de blocage.
Évitez toute opération bloquante sur le thread principal. Au lieu de synchronized, utilisez ConcurrentHashMap ; au lieu de Thread.join() — des coroutines avec async/await. Cette règle s'applique à tout langage sur Android : Java, Kotlin ou C++ via JNI.
BroadcastReceiver s'exécute sur le thread principal par défaut. Si onReceive() est occupé pendant plus de 10 secondes, Android affiche un ANR. Charger des données depuis une base de données ou un réseau dans onReceive est un chemin garanti vers le blocage.
Utilisez goAsync() dans BroadcastReceiver pour basculer vers un thread d'arrière-plan, ou registerReceiver avec getBackgroundBroadcastReceiver(). Cela permet de traiter les événements sans bloquer l'UI.
Les requêtes lourdes vers ContentProvider ou le travail direct avec SQLite sur le thread UI — une cause moins évidente mais fréquente d'ANR. Lors de la migration de base de données ou de l'insertion en masse de milliers d'enregistrements, le temps d'exécution peut dépasser la limite de 5 secondes.
Déplacez toutes les opérations base de données vers des threads d'arrière-plan en utilisant Room avec des fonctions suspend. Room vérifie automatiquement que la requête n'est pas exécutée sur le thread principal et lance une exception en cas de violation.
Diagnostiquer l'ANR diffère du débogage des exceptions normales — vous ne pouvez pas attraper l'ANR dans un bloc try-catch. La principale source d'information est le fichier traces.txt, qu'Android crée au moment du blocage.
traces.txt contient la pile d'appels de tous les threads de l'application au moment de l'ANR. Pour lire le fichier depuis un appareil réel, exécutez la commande adb bugreport, qui collecte un rapport système complet incluant tous les ANR récents. Pour un émulateur, le fichier est disponible dans /data/anr/traces.txt. La pile d'appels montre quelle méthode était exécutée sur le thread principal au moment du blocage.
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt
Google Play Console fournit la section ANR & Crash avec des rapports agrégés et des fréquences d'erreur. Pour chaque ANR, la pile d'appels et les statistiques de l'appareil sont affichées : modèle, version Android, région. Cela permet d'identifier les ANR qui dépendent d'appareils ou de versions système spécifiques.
Android Studio depuis 2021 inclut ANR Watchdog dans le profileur. Il enregistre automatiquement des vidages de threads si le thread principal ne répond pas pendant plus d'un temps seuil. L'outil montre une chronologie des événements : quelles opérations ont été lancées, quelles méthodes ont été exécutées et à quel stade le blocage s'est produit.
La prévention de l'ANR repose sur une règle fondamentale : le thread principal ne doit traiter que les événements UI. Toute opération de plus de 16 millisecondes (temps d'une image) doit être exécutée dans un thread d'arrière-plan.
StrictMode est un outil intégré Android pour détecter les ANR potentiels pendant le développement. Activez-le dans Application.onCreate() avec des indicateurs pour les opérations disque et réseau. En cas de violation, StrictMode lance une exception ou écrit dans logcat.
if (BuildConfig.DEBUG) {
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
.let { StrictMode.setThreadPolicy(it) }
}
Kotlin Coroutines — la méthode standard de travail asynchrone dans les applications Android modernes. L'approche principale : les opérations d'E/S s'exécutent sur Dispatchers.IO, le résultat est transmis à Dispatchers.Main pour les mises à jour UI. Pour les scénarios de type Flow, utilisez Dispatchers.Default pour les tâches intensives en CPU.
RxJava reste populaire dans les projets hérités. subscribeOn(Schedulers.io()) et observeOn(AndroidSchedulers.mainThread()) — l'ensemble minimum pour prévenir l'ANR. La règle principale est la même : aucun Observable ou Flowable ne doit émettre de données depuis le thread principal.
Firebase Crashlytics depuis la version SDK 18.4.0 prend en charge la surveillance ANR nativement. Pour Android 11+, Crashlytics utilise l'API système ApplicationExitInfo, qui fournit la raison exacte de la terminaison : ANR, Crash, ou kill système. Activez des clés personnalisées avec des paramètres d'écran et d'état pour une analyse contextuelle.
Cinq outils couvrent toutes les étapes du travail avec l'ANR : du débogage sur une station de travail à la surveillance en production. Chaque outil résout sa propre tâche et fournit des données pour différents scénarios.
| Outil | Objectif | Format de données |
|---|---|---|
| StrictMode | Détection pendant le développement | Logcat / Exception |
| ANR Watchdog (Android Studio) | Traçage en temps réel | Thread dump + timeline |
| Google Play Console | Statistiques agrégées | ANR rate + stack traces |
| Firebase Crashlytics | Surveillance en production | ApplicationExitInfo |
| adb bugreport | Rapport système complet | traces.txt + logcat + dmesg |
Chaque outil a sa propre niche : StrictMode détecte les violations évidentes aux premiers stades, Crashlytics montre la fréquence réelle des ANR chez les utilisateurs, et adb bugreport fournit l'image la plus complète pour les cas complexes. Combinez-les pour une couverture totale.
Firebase Performance suit le temps de réponse du thread UI et crée automatiquement des traces pour les opérations suspectes longues. Si le thread principal bloque pendant plus de 500 ms, Performance enregistre une trace personnalisée avec le nom de la méthode responsable. Cela permet de détecter les scénarios d'ANR sans intervention de l'utilisateur et avant qu'ils ne deviennent critiques.
L'intégration avec Firebase Crashlytics donne une image complète : Performance montre les ralentissements avant l'ANR, et Crashlytics montre le blocage lui-même. Configurez des alertes dans Firebase Console pour un taux d'ANR supérieur à 0,1 %, et vous recevrez des notifications sur les nouveaux problèmes avant les plaintes massives des utilisateurs.
Foire aux questions
ANR est un blocage où l'application ne répond pas mais reste en mémoire. Crash est une terminaison anormale complète avec sortie du processus. L'ANR peut être “survécu” si le système ou l'utilisateur attend une réponse, tandis que le Crash termine toujours l'application.
Non. ANR n'est pas une exception Java/Kotlin, mais un signal système au niveau des processus (SIGQUIT). Un développeur ne peut pas le gérer dans le code de l'application. La seule façon de répondre à ANR est d'analyser les rapports après le redémarrage.
Les performances de l'appareil, la version d'Android, la charge CPU et le nombre de processus en arrière-plan affectent la probabilité d'ANR. Sur les appareils faibles, la même opération peut prendre 2 à 3 fois plus de temps, dépassant la limite de 5 secondes.
10 secondes pour un BroadcastReceiver normal dans onReceive(). Pour les services au premier plan, la limite est de 20 secondes, et pour ContentProvider — il n'y a pas de limite explicite, mais bloquer le thread principal pendant plus de 5 secondes provoque toujours un ANR.
Activez StrictMode dans toutes les versions de débogage, ajoutez une surveillance via Firebase Crashlytics et utilisez adb bugreport lorsque ANR se produit. Les ANR irréguliers sont souvent liés à des conditions de concurrence ou à des états réseau spécifiques.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi