Lorsque le thread UI d'une application Android est bloqué trop longtemps, le système déclenche une erreur ANR (« L'application ne répond pas »). Cette page décrit les différents types d'erreurs ANR, explique comment les diagnostiquer et propose des solutions pour les résoudre. Toutes les plages de délais avant expiration par défaut s'appliquent aux appareils AOSP et Pixel. Ces délais peuvent varier selon les OEM.
Notez bien que, lorsque vous déterminez la cause des erreurs ANR, il est utile de faire la distinction entre les problèmes du système et ceux de l'application.
Lorsque le système est dans un état défectueux, les problèmes suivants peuvent entraîner des erreurs ANR :
- Les problèmes temporaires sur le serveur système ralentissent généralement les appels de liaison.
- Des problèmes liés au serveur système et à une charge élevée de l'appareil empêchent la planification des threads d'application.
Le cas échéant, un bon moyen de faire la distinction entre les problèmes du système et ceux de l'application consiste à utiliser des traces de Perfetto :
- Vérifiez si le thread principal de l'application est planifié en consultant le suivi de l'état du thread dans Perfetto pour voir s'il est en cours d'exécution ou exécutable.
- Recherchez d'éventuels problèmes dans les threads
system_server
, tels que les conflits de verrouillage. - Pour les appels de liaison lents, examinez le thread de réponse s'il est présent pour en comprendre la raison.
Délai avant expiration de distribution des entrées
Les erreurs ANR de distribution des entrées se produisent lorsque le thread principal de l'application ne répond pas à temps à un événement d'entrée, tel qu'un balayage ou une pression sur une touche. Étant donné que l'application est exécutée au premier plan lorsque des délais avant expiration de distribution des entrées se produisent, ils sont presque toujours visibles par l'utilisateur, et il est important de les limiter.
Délai avant expiration par défaut : 5 secondes.
Les erreurs ANR de distribution des entrées sont généralement causées par des problèmes sur le thread principal. Si le thread principal a été bloqué en attendant l'obtention d'un verrou, le thread du conteneur peut également être impliqué.
Pour éviter les erreurs ANR de distribution des entrées, suivez ces bonnes pratiques :
- N'effectuez pas d'opérations bloquantes ou de longue durée sur le thread principal. Envisagez d'utiliser
StrictMode
pour détecter toute activité accidentelle sur le thread principal. - Minimisez les conflits de verrouillage entre le thread principal et les autres threads.
- Réduisez les tâches autres que celles liées à l'interface utilisateur sur le thread principal, par exemple lors de la gestion des broadcasts ou de l'exécution de services.
Causes courantes
Voici quelques causes courantes et suggestions de solutions pour les erreurs ANR de distribution des entrées.
Cause | Que se passe-t-il | Solutions suggérées |
---|---|---|
Appel de liaison lent | Le thread principal effectue un long appel de liaison synchrone. | Déplacez l'appel en dehors du thread principal ou essayez de l'optimiser, si vous êtes propriétaire de l'API. |
Nombreux appels de liaison consécutifs | Le thread principal effectue de nombreux appels de liaison synchrones consécutifs. | N'effectuez pas d'appels de liaison dans une boucle étroite. |
E/S bloquantes | Le thread principal effectue des appels d'E/S bloquants, tels que l'accès à la base de données ou au réseau. | Retirez toutes les E/S bloquantes du thread principal. |
Conflits de verrouillage | Le thread principal est bloqué en attendant d'obtenir un verrou. | Réduisez les conflits de verrouillage entre le thread principal et un thread différent. Optimisez le code lent dans un thread différent. |
Frame coûteux en ressources | Trop d'affichages sur un seul frame, ce qui entraîne de graves à-coups | Simplifiez l'affichage du frame. N'utilisez pas les algorithmes n2. Utilisez des composants efficaces pour le défilement ou la pagination, comme la bibliothèque Paging de Jetpack. |
Bloqué par un autre composant | Un autre composant, tel qu'un broadcast receiver, est en cours d'exécution et bloque le thread principal. | Retirez autant que possible les tâches qui ne sont pas liées à l'UI du thread principal. Exécutez des broadcast receivers sur un thread différent. |
Blocage du GPU | Le blocage du GPU est un problème système ou matériel qui entraîne le blocage de l'affichage et, par conséquent, une erreur ANR de distribution des entrées. | Malheureusement, il n'existe généralement pas de solutions du côté de l'application. Si possible, contactez l'équipe chargée du matériel pour résoudre le problème. |
Comment déboguer
Commencez le débogage en examinant la signature du groupe d'erreurs ANR dans la Google Play Console ou dans Firebase Crashlytics. Le groupe contient généralement les frames supérieurs susceptibles de provoquer l'erreur ANR.
L'organigramme suivant montre comment déterminer la cause d'une erreur ANR du délai avant expiration de distribution des entrées.
![](https://developer.android.google.cn/static/topic/performance/images/debug-input-dispatch-anr.png?authuser=6&hl=fr)
Play Vitals peut détecter et déboguer certaines de ces causes d'erreurs ANR courantes. Par exemple, si Vitals détecte qu'une erreur ANR s'est produite en raison d'un conflit de verrouillage, l'appli peut résumer le problème et la solution recommandée dans la section Insights sur les erreurs ANR.
![](https://developer.android.google.cn/static/topic/performance/images/play-vitals-anr-detection.png?authuser=6&hl=fr)
Aucune fenêtre sélectionnée
Alors que les événements tels que les gestes tactiles sont envoyés directement à la fenêtre appropriée en fonction des tests de positionnement, les événements comme les touches ont besoin d'une cible. Cette cible est appelée fenêtre sélectionnée. Il n'y a qu'une seule fenêtre sélectionnée par écran, qui correspond généralement à celle avec laquelle l'utilisateur interagit actuellement. Si une fenêtre sélectionnée ne peut être trouvée, l'entrée génère une erreur ANR de fenêtre sans sélection. Une erreur ANR de fenêtre sans sélection est un type d'erreur ANR de distribution des entrées.
Délai avant expiration par défaut : 5 secondes.
Causes courantes
Les erreurs ANR de fenêtre sans sélection sont généralement causées par l'un des problèmes suivants :
- L'appli effectue trop de tâches et est trop lente pour dessiner le premier frame.
- La fenêtre principale n'est pas sélectionnable. Si une fenêtre est signalée par l'icône
FLAG_NOT_FOCUSABLE
, l'utilisateur ne peut pas lui envoyer d'événements de touche ou de bouton.
Kotlin
override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) window.addFlags(WindowManager.LayoutParams.FLAG_FLAG_NOT_FOCUSABLE) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); }
Délai avant expiration du broadcast receiver
Une erreur ANR de broadcast receiver se produit lorsqu'un broadcast receiver ne gère pas une diffusion à temps. Pour les récepteurs synchrones ou qui n'appellent pas goAsync()
, un délai avant expiration signifie que onReceive()
ne s'est pas terminé à temps. Pour les récepteurs asynchrones, ou les récepteurs qui appellent goAsync()
, un délai avant expiration signifie que PendingResult.finish()
n'a pas été appelé à temps.
Les erreurs ANR du broadcast receiver se produisent souvent dans les threads suivants :
- Thread principal, en cas de démarrage lent de l'application.
- Thread exécutant un broadcast receiver, si le problème est une lenteur du code
onReceive()
. - Diffusion des threads de travail, si le problème est une lenteur du code de diffusion
goAsync()
.
Pour éviter les erreurs ANR du broadcast receiver, suivez ces bonnes pratiques :
- Assurez-vous que l'application démarre rapidement, car elle est comptabilisée dans le délai avant expiration de l'erreur ANR si l'application est lancée pour gérer la diffusion.
- Si
goAsync()
est utilisé, assurez-vous quePendingResult.finish()
est appelé rapidement. Elle est soumise au même délai avant expiration de l'erreur ANR que les broadcast receivers synchrones. - Si
goAsync()
est utilisé, assurez-vous que le ou les threads de travail ne sont pas partagés avec d'autres opérations de longue durée ou bloquantes. - Envisagez d'utiliser
registerReceiver()
pour exécuter des broadcast receivers dans un thread non principal afin d'éviter de bloquer le code de l'interface utilisateur exécuté dans le thread principal.
Délais avant expiration
Les délais avant expiration des broadcast receivers varient selon que l'indicateur d'intent de premier plan est défini ou non, et selon la version de la plate-forme.
Type d'intent | Android 13 ou version antérieure | Android 14 ou version ultérieure |
---|---|---|
Intent de priorité au premier plan ( |
10 secondes |
10 à 20 secondes, selon que le processus manque de ressources de processeur ou non |
Intent de priorité en arrière-plan ( |
60 secondes |
60 à 120 secondes, selon que le processus manque de ressources de processeur ou non |
Pour savoir si l'indicateur FLAG_RECEIVER_FOREGROUND
est défini, recherchez "flg=" dans l'objet de l'erreur ANR et vérifiez la présence de 0x10000000
. Si ce bit est défini, FLAG_RECEIVER_FOREGROUND
est défini pour l'intent, ce qui réduit le délai avant expiration.
Exemple d'objet de l'erreur ANR avec un délai avant expiration de diffusion court (10 à 20 secondes) :
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Exemple d'objet de l'erreur ANR avec un délai avant expiration de diffusion long (de 60 à 120 secondes) :
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Comment les temps de diffusion sont-ils mesurés ?
La mesure de la durée de diffusion commence lorsque la diffusion est envoyée depuis system_server
vers l'application et se termine lorsque l'application a terminé le traitement de la diffusion. Si le processus de l'application n'était pas déjà en cours d'exécution, elle doit également effectuer un démarrage à froid pendant le délai avant expiration de l'erreur ANR. Par conséquent, un démarrage lent de l'application peut entraîner des erreurs ANR du broadcast receiver.
L'image suivante illustre la chronologie des erreurs ANR du broadcast receiver sur certains processus d'application.
![](https://developer.android.google.cn/static/topic/performance/images/broadcast-receiver-anr-timeline.png?authuser=6&hl=fr)
La mesure du délai avant expiration de l'erreur ANR se termine lorsque le récepteur termine le traitement de la diffusion. Le moment exact où cela se produit dépend du type de récepteur synchrone ou asynchrone.
- Pour les récepteurs synchrones, la mesure s'arrête lorsque
onReceive()
est renvoyé. - Pour les récepteurs asynchrones, la mesure s'arrête lorsque
PendingResult.finish()
est appelé.
![](https://developer.android.google.cn/static/topic/performance/images/sync-async-measurement-end.png?authuser=6&hl=fr)
Causes courantes
Voici quelques causes courantes et suggestions de solutions pour les erreurs ANR du broadcast receiver.
Cause | S'applique à | Que s'est-il passé | Solution suggérée |
---|---|---|---|
Démarrage lent de l'appli | Tous les récepteurs | L'application a mis trop de temps à effectuer un démarrage à froid. | Optimisez le démarrage lent de l'application. |
onReceive() non planifié | Tous les récepteurs | Le thread du broadcast receiver était occupé à effectuer d'autres tâches et n'a pas pu démarrer la méthode onReceive() . | N'effectuez pas de tâches de longue durée sur le thread récepteur (ou déplacez le récepteur vers un thread dédié). |
onReceive() lent | Tous les récepteurs, mais principalement les récepteurs synchrones | La méthode onReceive() a démarré, mais a été bloquée ou lente, et ne s'est donc pas terminée à temps. | Optimisez le code du récepteur lent. |
Tâches du récepteur asynchrone non planifiées | Récepteurs goAsync() | La méthode onReceive() a tenté d'exécuter une tâche sur un pool de threads de travail bloqué. Par conséquent, la tâche n'a jamais démarré. |
Optimisez les appels lents ou bloquants, ou utilisez des threads différents pour les workers de diffusion par rapport aux autres tâches de longue durée. |
Workers lents ou bloqués | Récepteurs goAsync() |
Une opération bloquante ou lente s'est produite dans le pool de threads de travail lors du traitement de la diffusion. PendingResult.finish n'a donc pas été appelé à temps. | Optimisez le code lent du récepteur async . |
Vous avez oublié d'appeler PendingResult.finish |
Récepteurs goAsync() |
Il manque l'appel à finish() dans le chemin de code. |
Assurez-vous que finish() est toujours appelé. |
Comment déboguer
Sur la base de la signature du groupe et du rapport ANR, vous pouvez localiser le thread sur lequel le récepteur s'exécute, puis le code spécifique qui est manquant ou qui s'exécute lentement.
L'organigramme suivant montre comment déterminer la cause d'une erreur ANR sur le broadcast receiver.
![](https://developer.android.google.cn/static/topic/performance/images/debug-broadcast-receiver-timeout-anr.png?authuser=6&hl=fr)
Trouver le code du récepteur
La Google Play Console affiche la classe du récepteur et l'intent de diffusion dans la signature de l'erreur ANR. Recherchez les éléments suivants :
cmp=<receiver class>
act=<broadcast_intent>
Voici un exemple de signature de l'erreur ANR d'un broadcast receiver :
com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }
Rechercher le thread qui exécute la méthode onReceive()
Si vous utilisez Context.registerReceiver
pour spécifier un gestionnaire personnalisé, c'est le thread qui exécute ce gestionnaire. Sinon, il s'agit du thread principal.
Exemple : Tâches de récepteur asynchrone non planifiées
Cette section présente un exemple de débogage d'une erreur ANR d'un broadcast receiver.
Supposons que la signature de l'erreur ANR se présente comme suit :
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
D'après la signature, il semble que l'intent de diffusion soit android.accounts.LOG_ACCOUNTS_CHANGED
et que la classe du récepteur soit com.example.app.MyReceiver
.
À partir du code du récepteur, vous pouvez déterminer que le pool de threads "BG Thread [0,1,2,3]" effectue la tâche principale pour traiter cette diffusion. En examinant les vidages de pile, vous pouvez constater que les quatre threads d'arrière-plan (BG) ont le même schéma ; ils exécutent un appel bloquant, getDataSync
. Étant donné que tous les threads de BG étaient occupés, la diffusion n'a pas pu être traitée à temps, ce qui a entraîné une erreur ANR.
BG Thread #0 (tid=26) Waiting
at jdk.internal.misc.Unsafe.park(Native method:0)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:211)
at com.google.common.util.concurrent.AbstractFuture.get(AbstractFuture:563)
at com.google.common.util.concurrent.ForwardingFuture.get(ForwardingFuture:68)
at com.example.app.getDataSync(<MyClass>:152)
...
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
at com.google.android.libraries.concurrent.AndroidExecutorsModule.lambda$withStrictMode$5(AndroidExecutorsModule:451)
at com.google.android.libraries.concurrent.AndroidExecutorsModule$$ExternalSyntheticLambda8.run(AndroidExecutorsModule:1)
at java.lang.Thread.run(Thread.java:1012)
at com.google.android.libraries.concurrent.ManagedPriorityThread.run(ManagedPriorityThread:34)
There are several approaches to fix the issue:
- Find out why
getDataSync
is slow and optimize. - Don't run
getDataSync
on all four BG threads. - More generally, ensure that the BG thread pool isn't saturated with long-running operations.
- Use a dedicated thread pool for
goAsync
worker tasks. - Use an unbounded thread pool instead of the bounded BG thread pool
Example: slow app startup
A slow app startup can cause several types of ANRs, especially broadcast
receiver and execute service ANRs. The cause of an
ANR is likely slow app startup if you see ActivityThread.handleBindApplication
in the main thread stacks.
Execute service timeout
An execute service ANR happens when the app's main thread doesn't start a
service in time. Specifically, a service doesn't finish executing
onCreate()
and onStartCommand()
or onBind()
within the
timeout period.
Default timeout period: 20 seconds for foreground service; 200 seconds for
background service. The ANR timeout period includes the app cold start, if
necessary, and calls to onCreate(), onBind()
, or onStartCommand()
.
To avoid execute service ANRs, follow these general best practices:
- Make sure that app startup is fast, since it's counted in the ANR timeout if the app is started to run the service component.
- Make sure that the service's
onCreate()
,onStartCommand()
, andonBind()
methods are fast. - Avoid running any slow or blocking operations on the main thread from other components; these operations can prevent a service from starting quickly.
Common causes
The following table lists common causes of execute service ANRs and suggested fixes.
Cause | What | Suggested fix |
---|---|---|
Slow app startup | The app takes too long to perform a cold start. | Optimize slow app start. |
Slow onCreate(), onStartCommand (), or
onBind() |
The service component's onCreate(),
onStartCommand (), or onBind() method takes too long to
execute on the main thread. |
Optimize slow code. Move slow operations off the critical path where possible. |
Not scheduled (main thread blocked before onStart() ) |
The app's main thread is blocked by another component before the service can be started. | Move other component's work off the main thread. Optimize other component's blocking code. |
How to debug
From the cluster signature and ANR report in Google Play Console or Firebase Crashlytics, you can often determine the cause of the ANR based on what the main thread is doing.
The following flow chart describes how to debug an execute service ANR.
![](https://developer.android.google.cn/static/topic/performance/images/debug-execute-service-anr.png?authuser=6&hl=fr)
If you've determined that the execute service ANR is actionable, follow these steps to help resolve the issue:
Find the service component class in the ANR signature. In Google Play Console, the service component class is shown in the ANR signature. In the following example ANR details, it's
com.example.app/MyService
.com.google.common.util.concurrent.Uninterruptibles.awaitUninterruptibly Executing service com.example.app/com.example.app.MyService
Determine whether the slow or block operation is part of app startup, the service component, or elsewhere by checking for the following important function call(s) in the main threads.
Function call(s) in main thread stacks What it means android.app.ActivityThread.handleBindApplication
App was starting up, so the ANR was caused by slow app start. <ServiceClass>.onCreate()
[...]
android.app.ActivityThread.handleCreateService
Service was being created, so the ANR was likely caused by slow onCreate()
code.<ServiceClass>.onBind()
[...]
android.app.ActivityThread.handleBindService
Service was being bound, so the ANR was likely caused by slow onBind()
code.<ServiceClass>.onStartCommand()
[...]
android.app.ActivityThread.handleServiceArgs
Service was being started, so the ANR was likely caused by slow onStartCommand()
code.For example, if the
onStartCommand()
method in theMyService
class is slow, the main threads will look like this:at com.example.app.MyService.onStartCommand(FooService.java:25) at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4820) at android.app.ActivityThread.-$$Nest$mhandleServiceArgs(unavailable:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2289) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:205) at android.os.Looper.loop(Looper.java:294) at android.app.ActivityThread.main(ActivityThread.java:8176) at java.lang.reflect.Method.invoke(Native method:0)
Si vous ne voyez aucun des appels de fonction importants, il existe plusieurs autres possibilités :
- Le service est en cours d'exécution ou en cours d'arrêt, ce qui signifie que les piles sont prises trop tard. Dans ce cas, vous pouvez ignorer l'ANR en tant que faux positif.
- Un autre composant d'application est en cours d'exécution, comme un broadcast receiver. Dans ce cas, le thread principal est probablement bloqué dans ce composant, ce qui empêche le démarrage du service.
Si vous voyez un appel de fonction clé et pouvez déterminer où l'erreur ANR se produit généralement, vérifiez le reste des piles de threads principaux pour identifier l'opération lente, et optimisez-la ou retirez-la du chemin critique.
- Assurez-vous que l'application démarre rapidement, car elle est comptabilisée dans le délai avant expiration de l'erreur ANR si l'application est lancée pour exécuter le fournisseur de contenu.
- Assurez-vous que les requêtes du fournisseur de contenu sont rapides.
- N'effectuez pas de nombreux appels de liaison bloquants simultanés qui peuvent bloquer tous les threads de liaison de l'application.
- Vidage tardif de la pile. Le thread a été récupéré pendant la courte période entre le déclenchement de l'ANR et le vidage des piles. La latence dans Pixels sur Android 13 est d'environ 100 ms, mais peut dépasser 1 s. Sous Android 14, la latence dans Pixels est généralement inférieure à 10 ms.
- Erreur d'attribution du thread. Le thread utilisé pour créer la signature de l'erreur ANR n'était pas celui qui n'a pas répondu à l'origine de l'erreur ANR. Dans ce cas, essayez de déterminer si l'erreur ANR est de l'un des types suivants :
- Problème au niveau du système. Le processus n'a pas été planifié en raison d'une charge système importante ou d'un problème au niveau du serveur système.
- La pile prend trop de temps et dépasse le délai.
- Le processus a expiré ou a été arrêté avant la prise des piles.
Pour en savoir plus sur les services, consultez les pages suivantes :
Le fournisseur de contenu ne répond pas
Une erreur ANR de fournisseur de contenu se produit lorsqu'un fournisseur de contenu distant prend plus de temps que le délai avant expiration pour répondre à une requête et qu'il est arrêté.
Délai avant expiration par défaut : Spécifié par le fournisseur de contenu à l'aide de ContentProviderClient.setDetectNotResponding
. Le délai avant expiration de l'erreur ANR inclut la durée totale d'exécution d'une requête de fournisseur de contenu distant, ce qui comprend le démarrage à froid de l'application à distance si elle n'était pas déjà en cours d'exécution.
Pour éviter les erreurs ANR de fournisseur de contenu, suivez ces bonnes pratiques :
Causes courantes
Le tableau suivant présente les causes courantes d'erreurs ANR de fournisseur de contenu et les solutions suggérées.
Cause | Que se passe-t-il | Signal | Solution suggérée |
---|---|---|---|
Requête du fournisseur de contenu lente | L'exécution du fournisseur de contenu prend trop de temps ou est bloquée. | Le frame android.content.ContentProvider$Transport.query se trouve dans le thread de liaison. |
Optimisez la requête du fournisseur de contenu. Identifiez ce qui bloque le thread de liaison. |
Démarrage lent de l'appli | Le démarrage de l'application du fournisseur de contenu prend trop de temps. | Le frame ActivityThread.handleBindApplication se trouve dans le thread principal. |
Optimisez le démarrage de l'application. |
Épuisement du thread de liaison : Tous les threads de liaison sont occupés | Tous les threads de liaison étant occupés à diffuser d'autres requêtes synchrones, l'appel de liaison du fournisseur de contenu ne peut pas s'exécuter. | L'application ne démarre pas, tous les threads de liaison sont occupés et le fournisseur de contenu n'est pas en cours d'exécution. | Réduisez la charge sur les threads de liaison. Autrement dit, effectuez moins d'appels de liaison sortants synchrones ou réduisez vos tâches lors de la gestion des appels entrants. |
Comment déboguer
Pour déboguer les erreurs ANR d'un fournisseur de contenu à l'aide de la signature du groupe et du rapport ANR dans la Google Play Console ou dans Firebase Crashlytics, examinez ce que font le thread principal et le ou les threads de liaison.
L'organigramme suivant explique le débogage d'une erreur ANR de fournisseur de contenu :
![](https://developer.android.google.cn/static/topic/performance/images/debug-content-provider-anr.png?authuser=6&hl=fr)
L'extrait de code suivant montre à quoi ressemble le thread de liaison lorsqu'il est bloqué en raison d'une requête du fournisseur de contenu lente. Dans ce cas, la requête du fournisseur de contenu attend le verrouillage lors de l'ouverture d'une base de données.
binder:11300_2 (tid=13) Blocked
Waiting for osm (0x01ab5df9) held by at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers:182)
at com.example.app.MyClass.blockingGetOpenDatabase(FooClass:171)
[...]
at com.example.app.MyContentProvider.query(MyContentProvider.java:915)
at android.content.ContentProvider$Transport.query(ContentProvider.java:292)
at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:107)
at android.os.Binder.execTransactInternal(Binder.java:1339)
at android.os.Binder.execTransact(Binder.java:1275)
L'extrait de code suivant montre à quoi ressemble le thread principal lorsqu'il est bloqué en raison d'un démarrage lent de l'application. Dans ce cas, le démarrage de l'application est lent en raison d'un conflit de verrouillage lors de l'initialisation de Dagger.
main (tid=1) Blocked
[...]
at dagger.internal.DoubleCheck.get(DoubleCheck:51)
- locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
at com.myapp.Bar_Factory.get(Bar_Factory:38)
[...]
at com.example.app.MyApplication.onCreate(DocsApplication:203)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8170)
at java.lang.reflect.Method.invoke(Native method:0)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Réponse de tâche lente
Une erreur ANR de réponse de tâche est lente lorsque l'application met trop de temps à répondre à JobService.onStartJob()
ou JobService.onStopJob()
, ou met trop de temps à fournir une notification à l'aide de JobService.setNotification()
. Cela laisse supposer que le thread principal de l'application est bloqué et qu'il n'effectue pas d'autre action.
En cas de problème avec JobService.onStartJob()
ou JobService.onStopJob()
, vérifiez ce qui se passe sur le thread principal. En cas de problème avec JobService.setNotification()
, veillez à l'appeler aussi rapidement que possible.
Ne faites pas trop de tâches avant d'envoyer la notification.
ANR mystères
Parfois, la raison pour laquelle une erreur ANR se produit n'est pas claire, ou il n'y a pas assez d'informations pour la déboguer dans la signature du groupe et le rapport ANR. Dans ce cas, vous pouvez toujours prendre certaines mesures pour déterminer si l'erreur ANR est exploitable ou non.
File d'attente de messages inactive ou nativePollOnce
Si vous voyez le frame android.os.MessageQueue.nativePollOnce
dans les piles, cela signifie souvent que le thread qui ne répondait pas était en réalité inactif et attendait les messages du looper. Dans la Google Play Console, les informations détaillées sur l'ANR se présentent comme suit :
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Par exemple, si le thread principal est inactif, les piles se présentent comme suit :
"main" tid=1 NativeMain threadIdle
#00 pc 0x00000000000d8b38 /apex/com.android.runtime/lib64/bionic/libc.so (__epoll_pwait+8)
#01 pc 0x0000000000019d88 /system/lib64/libutils.so (android::Looper::pollInner(int)+184)
#02 pc 0x0000000000019c68 /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+112)
#03 pc 0x000000000011409c /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)
at android.os.MessageQueue.nativePollOnce (Native method)
at android.os.MessageQueue.next (MessageQueue.java:339) at android.os.Looper.loop (Looper.java:208)
at android.app.ActivityThread.main (ActivityThread.java:8192)
at java.lang.reflect.Method.invoke (Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:626)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1015)
Le thread soupçonné de ne pas répondre peut être inactif pour plusieurs raisons :
Aucun bloc de pile
Certains rapports ANR n'incluent pas les piles contenant les erreurs ANR, ce qui signifie que le vidage de la pile a échoué lors de la génération du rapport ANR. L'absence de blocs de pile peut s'expliquer par plusieurs raisons :
[...]
--- CriticalEventLog ---
capacity: 20
timestamp_ms: 1666030897753
window_ms: 300000
libdebuggerd_client: failed to read status response from tombstoned: timeout reached?
----- Waiting Channels: pid 7068 at 2022-10-18 02:21:37.<US_SOCIAL_SECURITY_NUMBER>+0800 -----
[...]
Les erreurs ANR sans bloc de pile ne sont pas exploitables à partir de la signature du groupe ou du rapport ANR. Pour effectuer le débogage, examinez les autres groupes de l'application. En effet, si un problème est suffisamment important, elle dispose généralement de son propre groupe contenant des blocs de pile. Vous pouvez également examiner les traces de Perfetto.
Problèmes connus
Le maintien d'un minuteur dans le processus de votre application afin de terminer le traitement de la diffusion avant le déclenchement d'une erreur ANR peut ne pas fonctionner correctement en raison de la manière asynchrone dont le système surveille les erreurs ANR.