Quando il thread UI di un'app Android è bloccato per troppo tempo, il sistema invia un messaggio di errore "L'applicazione non risponde" (ANR). In questa pagina vengono descritti i diversi tipi di ANR, come diagnosticarli e suggerimenti per correggerli. Tutti i gli intervalli di tempo di timeout predefiniti elencati sono relativi ai dispositivi AOSP e Pixel. questo orario può variare in base all'OEM.
Tieni presente che nel determinare la causa degli errori ANR è utile distinguere tra problemi di sistema e delle app.
Quando il sistema è in uno stato non valido, possono verificarsi errori ANR i seguenti problemi:
- I problemi temporanei al server di sistema causano in genere la rapida esecuzione di chiamate a binder lento.
- I problemi con il server di sistema e l'elevato carico del dispositivo causano il mancato completamento dei thread dell'app in fase di pianificazione.
Se disponibile, un buon modo per distinguere i problemi del sistema da quelli delle app è per utilizzare Tracce Perfetto:
- Controlla se il thread principale dell'app è pianificato esaminando lo stato del thread traccia Perfetto per vedere se è in esecuzione o eseguibile.
- Controlla i thread
system_server
per verificare la presenza di problemi come il conflitto di blocchi. - Per le chiamate a binder lente, guarda il thread di risposta, se presente, per capire perché lento.
Timeout invio input
Gli errori ANR di invio dell'input si verificano quando il thread principale dell'app non risponde a un input ad esempio uno scorrimento o la pressione di un tasto. Poiché l'app è in primo piano quando si verificano timeout di invio dell'input, sono quasi sempre visibili all'utente e molto importante da mitigare.
Periodo di timeout predefinito: 5 secondi.
Gli errori ANR di invio dell'input sono generalmente causati da problemi nel thread principale. Se l'istanza principale il thread è stato bloccato in attesa di acquisire un blocco, anche il thread del titolare può essere coinvolti.
Per evitare errori ANR di invio degli input, segui queste best practice:
- Non eseguire operazioni di blocco o a lunga esecuzione sul thread principale. Prendi in considerazione
utilizzare
StrictMode
per rilevare video attività sul thread principale. - Riduci al minimo il conflitto di blocchi tra il thread principale e altri thread.
- Riduci al minimo il lavoro non relativo all'interfaccia utente sul thread principale, ad esempio durante la gestione delle trasmissioni dei servizi in esecuzione.
Cause comuni
Di seguito sono riportate alcune cause comuni e correzioni suggerite per gli errori ANR di invio degli input.
Causa | Che cosa succede | Correzioni suggerite |
---|---|---|
Chiamata a Binder lenta | Il thread principale effettua una lunga chiamata a binder sincrona. | Sposta la chiamata dal thread principale o prova a ottimizzare la chiamata, se proprietario dell'API. |
Molte chiamate a binder consecutive | Il thread principale effettua molte chiamate a binder sincrone consecutive. | Non eseguire chiamate a binder in un loop stretto. |
Bloccare l'I/O | Il thread principale effettua la chiamata I/O di blocco, ad esempio il database o la rete l'accesso. | Sposta tutti gli IO di blocco dal thread principale. |
Conflitto blocco | Il thread principale è bloccato in attesa di acquisire un blocco. | Riduci il conflitto del blocco tra il thread principale e l'altro thread. Ottimizza il codice lento nell'altro thread. |
Cornice costosa | Rendering eccessivo in un solo frame, con conseguenti jank gravi. | Riduci il lavoro di piegatura. Non utilizzare n2 algoritmi. Utilizza le funzionalità di componenti efficienti per lo scorrimento o il paging, ad esempio Jetpack Libreria di pacchetti. |
Bloccata da un altro componente | Un altro componente, ad esempio un broadcast receiver, è in esecuzione e bloccando il thread principale. | Sposta il più possibile il lavoro non UI dal thread principale. Esegui trasmissione su un thread diverso. |
Blocco GPU | Il blocco della GPU è un problema del sistema o dell'hardware che causa bloccare il rendering e, di conseguenza, un errore ANR di invio di input. | Purtroppo di solito non sono disponibili correzioni per l'app. Se contatta il team addetto all'hardware per risolvere il problema. |
Come eseguire il debug
Inizia il debug osservando la firma del cluster ANR in Google Play Console o Firebase Crashlytics. In genere il cluster contiene i cluster i frame che si sospetta causino l'errore ANR.
Il seguente diagramma di flusso mostra come determinare la causa di un timeout dell'input invia l'errore ANR.
Play vitals può rilevare e contribuire a eseguire il debug di alcune di queste cause di ANR comuni. Per Ad esempio, se i parametri vitals rilevano che si è verificato un errore ANR a causa della contesa del blocco, Puoi riassumere il problema e la correzione consigliata nella sezione Approfondimenti sugli errori ANR.
Nessuna finestra con lo stato attivo
Mentre gli eventi come il tocco vengono inviati direttamente alla finestra pertinente in base all'hit durante il test, eventi come le chiavi richiedono una destinazione. Questo target è indicato come finestra con lo stato attivo. C'è una sola finestra attiva per display e di solito la finestra con cui l'utente sta attualmente interagendo. Se una finestra con lo stato attivo non è possibile trovare, l'input genera un errore ANR su una finestra non focalizzata. Un errore ANR su una finestra non attiva è un tipo di errore ANR di invio dell'input.
Periodo di timeout predefinito: 5 secondi.
Cause comuni
Gli errori ANR senza uno stato attivo di una finestra di solito sono causati da uno dei seguenti problemi:
- L'app sta svolgendo troppo lavoro ed è troppo lenta per disegnare il primo frame.
- Non è possibile attivare la finestra principale. Se una finestra è contrassegnata con
FLAG_NOT_FOCUSABLE
, l'utente non può inviare eventi chiave o pulsante.
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); }
Timeout del ricevitore di trasmissione
Si verifica un errore ANR del broadcast receiver quando un broadcast receiver non gestisce un
in tempo. Per ricevitori sincroni o ricevitori che non chiamano
goAsync()
, un timeout significa che onReceive()
non è stato completato in
nel tempo. Per i ricevitori asincroni o che chiamano goAsync()
, un timeout significa
che PendingResult.finish()
non è stato chiamato in tempo.
Gli ANR del ricevitore di trasmissione si verificano spesso in questi thread:
- Thread principale, se il problema è l'avvio lento dell'app.
- Thread che esegue il broadcast receiver se il problema è legato al codice
onReceive()
lento. - Trasmetti thread worker se il problema è un codice di trasmissione
goAsync()
lento.
Per evitare gli errori ANR del broadcast receiver, segui queste best practice:
- Assicurati che l'avvio dell'app sia veloce, poiché viene conteggiato nel timeout dell'ANR se l'app inizia a gestire la trasmissione.
- Se viene utilizzata
goAsync()
, assicurati chePendingResult.finish()
venga chiamato rapidamente. È soggetto allo stesso timeout ANR dei broadcast receiver sincroni. - Se utilizzi
goAsync()
, assicurati che i thread di lavoro non siano condivisi con altre operazioni di blocco o a lunga esecuzione. - Potresti usare
registerReceiver()
per eseguire broadcast receiver in una thread non principale, per evitare di bloccare il codice UI in esecuzione nel thread principale.
Periodi di timeout
I periodi di timeout per la ricezione delle trasmissioni dipendono dal fatto che il flag di intent in primo piano o meno e la versione della piattaforma.
Tipo di intent | Android 13 e versioni precedenti | Android 14 e versioni successive |
---|---|---|
Intent di priorità in primo piano ( |
10 secondi |
10-20 secondi, a seconda che il processo sia esausto dalla CPU |
Intento di priorità in background ( |
60 secondi |
60-120 secondi, a seconda che il processo sia esausto dalla CPU |
Per capire se il flag FLAG_RECEIVER_FOREGROUND
è impostato, cerca "flg=" nel
L'oggetto dell'errore ANR e verifica la presenza di 0x10000000
. Se questo bit è impostato,
per l'intent è impostato FLAG_RECEIVER_FOREGROUND
e, di conseguenza, il timeout è più breve.
Esempio di soggetto ANR con timeout di trasmissione breve (10-20 secondi):
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Esempio di soggetto ANR con timeout di trasmissione lungo (60-120 secondi):
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Come si misurano i tempi di trasmissione
La misurazione della durata della trasmissione inizia quando viene inviata la trasmissione
system_server
all'app e termina quando l'app termina l'elaborazione
la trasmissione. Se il processo dell'app non era già in esecuzione, deve eseguire anche un cold
iniziano entro il periodo di timeout dell'ANR. Di conseguenza, un avvio lento dell'app può causare
gli errori ANR del broadcast receiver.
La figura seguente illustra la sequenza temporale dell'errore ANR del broadcast receiver allineata con determinati processi dell'app.
La misurazione del timeout dell'ANR termina quando il destinatario termina di elaborare broadcast: il momento esatto in cui accade dipende dal fatto che sia sincrona o un ricevitore asincrono.
- Per i ricevitori sincroni, la misurazione si interrompe quando ritorna
onReceive()
. - Per ricevitori asincroni, la misurazione si interrompe
Chiamata
PendingResult.finish()
.
Cause comuni
Di seguito sono riportate alcune cause comuni e correzioni suggerite per gli errori ANR del broadcast receiver.
Causa | Si applica a | Che cosa è successo | Correzione suggerita |
---|---|---|---|
Avvio dell'app lento | Tutti i destinatari | L'avvio a freddo dell'app ha richiesto troppo tempo. | Ottimizza l'avvio lento dell'app. |
onReceive() non programmato | Tutti i destinatari | Il thread del broadcast receiver era impegnato in altro modo e non poteva
avvia il metodo onReceive() . | Non eseguire di attività a lunga esecuzione sul thread del destinatario (oppure sposta il ricevitore sul thread). |
Dispositivo onReceive() lento | Tutti i ricevitori, ma principalmente sincroni | Il metodo onReceive() è stato avviato, ma
è stato bloccato o lento, quindi non è stato completato in tempo. | Ottimizzazione lenta il codice destinatario. |
Attività di ricezione asincrona non pianificate | goAsync()
ricevitori | Il metodo onReceive() ha provato a eseguire il lavoro
su un pool di thread worker bloccato, quindi il lavoro non è mai iniziato. |
Ottimizza le chiamate lente o di blocco oppure utilizza thread diversi per la trasmissione i worker rispetto ad altre attività di lunga durata. |
Worker lenti o bloccati | goAsync() ricevitore |
Si è verificata un'operazione lenta o blocco nel thread di lavoro
pool durante l'elaborazione della trasmissione. Quindi, PendingResult.finish
non è stato chiamato in tempo. | Ottimizza il ricevitore async lento
le API nel tuo codice. |
Ho dimenticato di chiamare PendingResult.finish |
goAsync() ricevitore |
Chiamata a finish() mancante nel percorso del codice. |
Assicurati che finish() venga sempre chiamato. |
Come eseguire il debug
In base alla firma del cluster e al report ANR, puoi individuare il thread su cui viene eseguito il ricevitore e il codice specifico mancante o in esecuzione lentamente.
Il seguente diagramma di flusso mostra come determinare la causa di una trasmissione l'errore ANR del ricevitore.
Trovare il codice destinatario
Google Play Console mostra la classe ricevente e l'intento di trasmissione nell'ANR firma. Cerca quanto segue:
cmp=<receiver class>
act=<broadcast_intent>
Ecco un esempio di firma ANR di 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 }
Trova il thread che esegue il metodo onReceive()
Se utilizzi Context.registerReceiver
per specificare un gestore personalizzato,
è il thread che esegue questo gestore. Altrimenti, si tratta del thread principale.
Esempio: attività di ricezione asincrone non programmate
Questa sezione illustra un esempio di come eseguire il debug dell'errore ANR di un broadcast receiver.
Supponiamo che la firma dell'errore ANR abbia il seguente aspetto:
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
In base alla firma, sembra che l'intenzione di trasmissione sia
android.accounts.LOG_ACCOUNTS_CHANGED
e la classe ricevente è
com.example.app.MyReceiver
.
Dal codice ricevitore, puoi determinare che il pool di thread "BG Thread
[0,1,2,3]" il lavoro principale per elaborare la trasmissione. Uno sguardo alla pila
dump, puoi vedere che tutti e quattro i thread in background (BG) hanno lo stesso pattern:
esegue una chiamata di blocco, getDataSync
. Poiché tutti i thread BG erano occupati,
non è stato possibile elaborare la trasmissione in tempo. Questo ha causato un errore 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.
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)
Se non riesci a vedere nessuna delle chiamate di funzione importanti, ci sono un paio di altre possibili:
- Il servizio è in esecuzione o è in fase di arresto, il che significa che gli stack troppo tardi. In questo caso, puoi ignorare l'errore ANR come falso positivo.
- È in esecuzione un altro componente dell'app, ad esempio un broadcast receiver. In questo se il thread principale è probabilmente bloccato in questo componente, impedendo l'avvio del servizio.
Se vedi una chiamata di funzione chiave e puoi determinare dove si trova l'errore ANR accade generalmente, controlla gli altri stack di thread principali per trovare operazioni e ottimizzarlo o allontanarlo dal percorso critico.
- Assicurati che l'avvio dell'app sia veloce, poiché viene conteggiato nel timeout dell'ANR se iniziamo con l'avvio dell'app a eseguire il fornitore di contenuti.
- Assicurati che le query dei fornitori di contenuti siano veloci.
- Non eseguire molte chiamate simultanei a binder di blocco che possono bloccare tutte le i thread di binder dell'app.
- dump dump dello stack in ritardo. Il thread è stato recuperato durante il breve periodo che intercorre tra L'attivazione di ANR e gli stack in fase di dump. La latenza in Pixel su Android 13 equivale a circa 100 ms, ma può superare 1 s. La latenza in Pixel su Android 14 è di solito meno di 10 ms.
- Mancata attribuzione dei thread. Il thread utilizzato per creare la firma ANR non era il thread che non risponde effettivamente che ha causato l'errore ANR. In questo caso, prova a determina se l'errore ANR è di uno dei seguenti tipi:
- Problema a livello di sistema. Il processo non è stato pianificato a causa di un carico elevato sul sistema o un problema nel server di sistema.
- Raccogliere lo stack richiede troppo tempo e si verifica il timeout.
- Il processo si è concluso o è stato interrotto prima che gli stack venissero presi.
Per ulteriori informazioni sui servizi, consulta le seguenti pagine:
Il fornitore di contenuti non risponde
Si verifica un errore ANR del fornitore di contenuti quando un fornitore di contenuti remoto impiega più di il periodo di timeout per rispondere a una query e viene interrotto.
Periodo di timeout predefinito: specificato dal fornitore di contenuti utilizzando
ContentProviderClient.setDetectNotResponding
Il periodo di timeout dell'ANR
include il tempo totale per l'esecuzione di una query sul fornitore di contenuti remoti, che
include l'avvio a freddo dell'app remota, se non era già in esecuzione.
Per evitare gli errori ANR dei fornitori di contenuti, segui queste best practice:
Cause comuni
Nella tabella che segue sono elencate le cause comuni degli errori ANR dei fornitori di contenuti e i suggerimenti correzioni.
Causa | Che cosa succede | Segnale | Correzione suggerita |
---|---|---|---|
Query lenta sul fornitore di contenuti | L'esecuzione del fornitore di contenuti richiede troppo tempo oppure è bloccato. | Il frame android.content.ContentProvider$Transport.query
è nel thread del binder. |
Ottimizza la query del fornitore di contenuti. Scopri cosa blocca il raccoglitore . |
Avvio dell'app lento | L'avvio dell'app del fornitore di contenuti richiede troppo tempo. | Il frame ActivityThread.handleBindApplication è nel
thread principale. |
Ottimizza l'avvio dell'app. |
Esaurimento dei thread del binder: tutti i thread del binder sono occupati | Tutti i thread di binder sono occupati a gestire altre richieste sincrone, quindi impossibile eseguire la chiamata a binder del fornitore di contenuti. | L'app non si avvia, tutti i thread di binder sono occupati e i contenuti che il provider non è in esecuzione. | Riduci il carico sui thread di binder. In altre parole, riduci il numero di chiamate in uscita sincrona più impegnativo per le chiamate o meno lavoro durante la gestione delle chiamate in arrivo. |
Come eseguire il debug
Per eseguire il debug dell'errore ANR del fornitore di contenuti utilizzando la firma del cluster e il report ANR in Google Play Console o Firebase Crashlytics, dai un'occhiata al thread principale thread binder.
Il seguente diagramma di flusso descrive come eseguire il debug dell'errore ANR del fornitore di contenuti:
Il seguente snippet di codice mostra l'aspetto del thread binder quando bloccato a causa di una query lenta del fornitore di contenuti. In questo caso, il fornitore di contenuti una query è in attesa di un blocco all'apertura di un database.
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)
Il seguente snippet di codice mostra l'aspetto del thread principale quando bloccato a causa di un avvio dell'app lento. In questo caso, l'avvio dell'app è lento a causa bloccare la contesa durante l'inizializzazione del pugnale.
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)
Risposta al job lenta
Si verifica un errore ANR di risposta al job lento quando l'app impiega troppo tempo per rispondere
JobService.onStartJob()
o JobService.onStopJob()
oppure impiega troppo tempo per
invia una notifica utilizzando JobService.setNotification()
. Questo suggerisce che
al thread principale dell'app non è consentito l'esecuzione di altre operazioni.
Se si tratta di un problema con JobService.onStartJob()
o JobService.onStopJob()
,
controllare cosa succede nel thread principale. Se si tratta di un problema di
JobService.setNotification()
, assicurati di chiamarla il più rapidamente possibile.
Non svolgere molto lavoro prima di inviare la notifica.
ANR misteriosi
A volte non è chiaro il motivo per cui si verifica un errore ANR o i dati non sono sufficienti informazioni per eseguirne il debug nel report ANR e sulla firma del cluster. In questi casi, puoi ancora svolgere alcuni passaggi per determinare se l'errore ANR sono ora fruibili.
Coda di messaggi inattiva o nativePollOnce
Se vedi il frame android.os.MessageQueue.nativePollOnce
nella
stack, spesso indica che il presunto thread che non risponde era in realtà
inattivo e in attesa di messaggi looper. In Google Play Console, i dettagli relativi all'errore ANR
ha questo aspetto:
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Ad esempio, se il thread principale è inattivo, gli stack hanno il seguente aspetto:
"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)
Esistono diversi motivi per cui il sospetto thread che non risponde può essere inattivo:
Nessuno stack frame
Alcuni report ANR non includono gli stack con l'errore ANR, il che significa che dumping dello stack non riuscito durante la generazione del report ANR. Ci sono un paio di Possibili motivi degli stack frame mancanti:
[...]
--- 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 -----
[...]
Gli errori ANR senza stack frame non sono strategici dalla firma del cluster o dall'errore ANR report. Per eseguire il debug, osserva altri cluster per l'app, poiché se un problema è di grandi dimensioni a sufficienza, di solito avrà un proprio cluster in cui sono presenti stack frame. Un'altra opzione è guardare le tracce Perfetto.
Problemi noti
Mantenere un timer nel processo dell'app al fine di terminare la procedura. la gestione della trasmissione prima che un trigger ANR non funzioni correttamente a causa la modalità asincrona di monitoraggio degli ANR.