Diagnostica e correggi gli errori ANR

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.

. Figura 1. Come eseguire il debug di un ANR di invio dell'input.

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.

. Figura 2. Rilevamento ANR di Play vitals.

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 che PendingResult.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

(FLAG_RECEIVER_FOREGROUND) imposta)

10 secondi

10-20 secondi, a seconda che il processo sia esausto dalla CPU

Intento di priorità in background

(FLAG_RECEIVER_FOREGROUND non impostata)

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.

. Figura 3. La sequenza temporale dell'errore ANR del broadcast receiver.

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().
di Gemini Advanced.
Figura 4. Endpoint di misurazione del timeout degli ANR per la sincronizzazione sincrona e asincroni.

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.

. Figura 5. Come eseguire il debug dell'errore ANR di un broadcast receiver.

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(), and onBind() 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.

Figure 6. 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:

  1. 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
    
  2. 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 the MyService 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.
  3. 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.

  4. 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:

    • 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.

    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:

    . Figura 7. 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:

    • 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.

    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:

    • Raccogliere lo stack richiede troppo tempo e si verifica il timeout.
    • Il processo si è concluso o è stato interrotto prima che gli stack venissero presi.
    [...]
    
    --- 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.