Diagnostica e correggi gli errori ANR

Quando il thread dell'interfaccia utente di un'app Android viene bloccato per troppo tempo, il sistema invia un errore "L'applicazione non risponde" (ANR). In questa pagina vengono descritti i diversi tipi di errori ANR, come diagnosticarli e i suggerimenti per correggerli. Tutti gli intervalli di tempo di timeout predefiniti elencati per i dispositivi AOSP e Pixel possono variare in base all'OEM.

Tieni presente che, quando determini la causa degli errori ANR, è utile fare una distinzione tra i problemi del sistema e delle app.

Quando il sistema è in uno stato non valido, i seguenti problemi possono causare errori ANR:

  • I problemi temporanei nel server di sistema causano in genere una lentezza delle chiamate a Binder veloce.
  • I problemi relativi al server di sistema e un carico elevato del dispositivo impediscono la pianificazione dei thread di app.

Se è disponibile, un buon modo per distinguere tra problemi di sistema e dell'app è utilizzare tracce Perfetto:

  • Per verificare se il thread principale dell'app è programmato, osserva la traccia dello stato del thread in Perfetto per vedere se è in esecuzione o eseguibile.
  • Controlla i thread system_server per verificare la presenza di problemi come la contesa dei blocchi.
  • Per le chiamate a Binder lenti, controlla 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 in tempo a un evento di input, ad esempio uno scorrimento o la pressione di un tasto. Poiché l'app è in primo piano quando si verificano timeout per l'invio di input, sono quasi sempre visibili all'utente ed è molto importante mitigare.

Periodo di timeout predefinito: 5 secondi.

Gli errori ANR dell'invio di input sono generalmente causati da problemi nel thread principale. Se il thread principale è stato bloccato in attesa di acquisizione di un blocco, può essere coinvolto anche il thread di supporto.

Per evitare errori ANR di invio dell'input, segui queste best practice:

  • Non eseguire operazioni di blocco o a lunga esecuzione sul thread principale. Potresti usare StrictMode per rilevare attività accidentali sul thread principale.
  • Riduci al minimo la contesa del blocco tra il thread principale e altri thread.
  • Riduci al minimo il lavoro non UI sul thread principale, ad esempio durante la gestione di trasmissioni o servizi in esecuzione.

Cause comuni

Di seguito sono riportate alcune cause comuni e correzioni suggerite per gli errori ANR di invio dell'input.

Motivo Che cosa succede Correzioni suggerite
Chiamata a Binder lenta Il thread principale esegue una lunga chiamata a Binder sincrona. Sposta la chiamata dal thread principale o prova a ottimizzarla, se sei il proprietario dell'API.
Numerose chiamate a Binder consecutive Il thread principale effettua molte chiamate a Binder sincrone consecutive. Non eseguire chiamate a Binder in un ciclo troppo stretto.
Blocco di I/O Il thread principale blocca le chiamate I/O, ad esempio l'accesso al database o alla rete. Sposta tutti gli IO di blocco dal thread principale.
Conflitto blocco Il thread principale è bloccato in attesa di acquisizione di un blocco. Riduci il conflitto di blocchi tra il thread principale e altri thread. Ottimizza il codice lento nell'altro thread.
Frame costoso Visualizzazione eccessiva in un singolo frame, con conseguente jank grave. Lavora meno a piegare il frame. Non utilizzare n2 algoritmi. Utilizza componenti efficienti per attività come lo scorrimento o il paging, ad esempio la libreria di creazione di pagine Jetpack.
Bloccata da un altro componente Un componente diverso, ad esempio un ricevitore di trasmissione, è in esecuzione e blocca il thread principale. Sposta il più possibile il lavoro non di UI dal thread principale. Esegui ricevitori broadcast su un thread diverso.
Blocco della GPU Il blocco della GPU è un problema di sistema o hardware che causa il blocco del rendering e, di conseguenza, un errore ANR di invio dell'input. Purtroppo, di solito non ci sono correzioni dall'app. Se possibile, contatta il team hardware per risolvere il problema.

Come eseguire il debug

Inizia il debug controllando la firma del cluster ANR in Google Play Console o in Firebase Crashlytics. Il cluster in genere contiene i top frame che si sospetta siano responsabili dell'errore ANR.

Il seguente diagramma di flusso mostra come determinare la causa di un errore ANR di invio tramite timeout di input.

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

Play vitals può rilevare ed eseguire il debug di alcune di queste cause comuni degli errori ANR. Ad esempio, se vitals rileva che si è verificato un errore ANR a causa di una contesa del blocco, può riassumere il problema e la correzione consigliata nella sezione Approfondimenti sugli errori ANR.

Figura 2. Rilevamento ANR di Play vitals.

Nessuna finestra attiva

Mentre gli eventi come il tocco vengono inviati direttamente alla finestra pertinente in base ai test sugli hit, gli eventi come i tasti richiedono un target. Questo target è definito finestra di interesse. Esiste una sola finestra attiva per display e di solito è la finestra con cui l'utente sta attualmente interagendo. Se non è possibile trovare una finestra attiva, l'input genera un ANR senza finestra attiva. Un errore ANR senza finestra attiva è un tipo di ANR di invio di input.

Periodo di timeout predefinito: 5 secondi.

Cause comuni

Gli errori ANR senza finestra principale sono generalmente causati da uno dei seguenti problemi:

  • L'app sta lavorando troppo ed è troppo lenta per disegnare il primo frame.
  • La finestra principale non è attivabile. Se una finestra è contrassegnata con FLAG_NOT_FOCUSABLE, l'utente non può inviarle 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 ricevitore trasmissione

Un ANR del ricevitore si verifica quando un ricevitore non gestisce in tempo la trasmissione. Per i ricevitori sincroni, o che non chiamano goAync(), un timeout indica che onReceive() non è stato completato in tempo. Per i ricevitori asincroni, o i ricevitori che chiamano goAsync(), un timeout significa che PendingResult.finish() non è stato chiamato in tempo.

Gli errori ANR del ricevitore della trasmissione si verificano spesso in questi thread:

  • Thread principale, se il problema è l'avvio lento dell'app.
  • Ricevitore di trasmissione Thread in esecuzione, se il problema è lento con il codice onReceive().
  • Thread worker di trasmissione, se il problema è lento: goAsync() codice di trasmissione.

Per evitare errori ANR del ricevitore della trasmissione, segui queste best practice:

  • Assicurati che l'avvio dell'app sia rapido, poiché viene conteggiato nel timeout ANR se l'app viene avviata a gestire la trasmissione.
  • Se viene utilizzato goAsync(), assicurati che PendingResult.finish() venga chiamato rapidamente. Questo è soggetto allo stesso timeout ANR dei ricevitori di trasmissione sincroni.
  • Se viene utilizzato goAsync(), assicurati che i thread worker non siano condivisi con altre operazioni di blocco o a lunga esecuzione.
  • Valuta l'utilizzo di registerReceiver() per eseguire ricevitori di broadcast in un thread non principale, per evitare di bloccare il codice UI in esecuzione nel thread principale.

Periodi di timeout

I periodi di timeout di ricezione della trasmissione dipendono dal fatto che sia impostato o meno il flag dell'intent in primo piano e dalla versione della piattaforma.

Tipo di intent Android 13 e versioni precedenti Android 14 e versioni successive

Intento priorità in primo piano

(FLAG_RECEIVER_FOREGROUND impostato)

10 secondi

10-20 secondi, a seconda che il processo non contenga CPU o meno

Intento priorità background

(FLAG_RECEIVER_FOREGROUND non impostato)

60 secondi

60-120 secondi, a seconda che il processo sia o meno a corto di CPU

Per capire se il flag FLAG_RECEIVER_FOREGROUND è impostato, cerca "flg=" nell'oggetto ANR e verifica la presenza di 0x10000000. Se questo bit è impostato, l'intent ha FLAG_RECEIVER_FOREGROUND impostato, 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 vengono misurati i tempi di trasmissione

La misurazione della durata della trasmissione inizia quando la trasmissione viene inviata da system_server all'app e termina quando l'app termina l'elaborazione della trasmissione. Se il processo dell'app non era già in esecuzione, deve eseguire anche un avvio a freddo entro il periodo di timeout ANR. Di conseguenza, un avvio lento dell'app può causare errori ANR del destinatario della trasmissione.

La figura seguente illustra la sequenza temporale ANR del ricevitore di trasmissione in linea con determinati processi dell'app.

Figura 3. La sequenza temporale ANR del ricevitore del broadcast.

La misurazione del timeout ANR termina quando il ricevitore termina l'elaborazione della trasmissione: il momento esatto in cui ciò si verifica dipende dal fatto che si tratti di un ricevitore sincrono o asincrono.

  • Per i ricevitori sincroni, la misurazione si interrompe quando ritorna onReceive().
  • Per i ricevitori asincroni, la misurazione si interrompe quando viene chiamata PendingResult.finish().
Figura 4. Endpoint di misurazione del timeout ANR per ricevitori sincroni e asincroni.

Cause comuni

Di seguito sono riportate alcune cause comuni e le correzioni suggerite per gli errori ANR del ricevitore televisivo.

Motivo Si applica a Che cosa è successo Correzione suggerita
Avvio dell'app lento Tutti i ricevitori L'avvio completo dell'app ha richiesto troppo tempo. Ottimizza l'avvio lento dell'app.
onReceive() non pianificate Tutti i ricevitori Il thread del ricevitore di trasmissione era impegnato in altre operazioni e non è stato possibile avviare il metodo onReceive(). Non eseguire attività a lunga esecuzione sul thread del destinatario (o sposta il destinatario nel thread dedicato).
Dispositivo onReceive() lento Tutti i ricevitori, ma principalmente quelli sincroni Il metodo onReceive() è stato avviato, ma è stato bloccato o è lento, quindi non è stato completato in tempo. Ottimizza il codice del ricevitore lento.
Attività ricevitore asincrone non pianificate goAsync() ricevitori Il metodo onReceive() ha tentato di eseguire il lavoro su un pool di thread di worker bloccato, pertanto il lavoro non è mai iniziato. Ottimizza le chiamate lente o bloccando le chiamate o utilizza thread diversi per i worker di tipo broadcast rispetto ad altre attività a lunga esecuzione.
Worker lenti o bloccati goAsync() ricevitori Si è verificata un'operazione di blocco o lenta in qualche punto del pool di thread di lavoro durante l'elaborazione della trasmissione. Di conseguenza, PendingResult.finish non è stato chiamato in tempo. Ottimizza il codice del ricevitore async lento.
Hai dimenticato di chiamare PendingResult.finish goAsync() ricevitori Manca la chiamata a finish() nel percorso del codice. Assicurati che finish() sia 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 destinatario, quindi il codice specifico mancante o in esecuzione lenta.

Il seguente diagramma di flusso mostra come determinare la causa di un errore ANR di un ricevitore di trasmissione.

Figura 5. Come eseguire il debug dell'ANR di un ricevitore di trasmissione.

Trova il codice del destinatario

Google Play Console mostra la classe del destinatario e l'intento di trasmissione nella firma ANR. Cerca quanto segue:

  • cmp=<receiver class>
  • act=<broadcast_intent>

Ecco un esempio di firma ANR del ricevitore di trasmissione:

com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }

Trovare il thread che esegue il metodo onRicevi()

Se utilizzi Context.registerReceiver per specificare un gestore personalizzato, è il thread che esegue questo gestore. In caso contrario, si tratta del thread principale.

Esempio: attività ricevitore asincroni non pianificate

Questa sezione illustra un esempio di come eseguire il debug di un ANR di un ricevitore di trasmissione.

Supponiamo che la firma ANR sia simile alla seguente:

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'intent di trasmissione sia android.accounts.LOG_ACCOUNTS_CHANGED e la classe del ricevitore sia com.example.app.MyReceiver.

Dal codice del ricevitore, puoi determinare che il pool di thread "BG Thread [0,1,2,3]" è il lavoro principale per elaborare questa trasmissione. Dando un'occhiata ai dump dello stack, puoi vedere che tutti e quattro i thread in background (BG) hanno lo stesso pattern: eseguono una chiamata di blocco, getDataSync. Poiché tutti i thread di chat erano occupati, non è stato possibile elaborare la trasmissione in tempo, causando 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 visualizzare nessuna delle chiamate di funzioni importanti, sono disponibili altre due possibilità:

    • Il servizio è in esecuzione o in fase di arresto, il che significa che gli stack vengono avviati troppo tardi. In questo caso, puoi ignorare l'ANR come falso positivo.
    • È in esecuzione un altro componente dell'app, ad esempio un ricevitore di trasmissione. In questo caso è probabile che il thread principale sia bloccato in questo componente e ciò impedisce l'avvio del servizio.
  3. Se vedi una chiamata a funzione chiave e puoi determinare dove si verifica l'errore ANR in generale, controlla il resto degli stack di thread principali per trovare l'operazione lenta e ottimizzarla oppure allontanarla dal percorso critico.

  4. Per ulteriori informazioni sui servizi, consulta le seguenti pagine:

    Il fornitore di contenuti non risponde

    Un ANR del fornitore di contenuti si verifica quando un fornitore di contenuti remoto impiega più tempo del 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 ANR include il tempo totale per l'esecuzione di una query sul fornitore di contenuti remoto, incluso l'avvio a freddo dell'app remota se non era già in esecuzione.

    Per evitare errori ANR dei fornitori di contenuti, segui queste best practice:

    • Assicurati che l'avvio dell'app sia rapido, poiché viene conteggiato nel timeout ANR se l'app inizia a eseguire il fornitore di contenuti.
    • Assicurati che le query del fornitore di contenuti siano veloci.
    • Non eseguire molte chiamate simultanee di binder di blocco che possono bloccare tutti i thread di binder dell'app.

    Cause comuni

    La seguente tabella elenca le cause comuni degli errori ANR dei fornitori di contenuti e le correzioni suggerite.

    Motivo Che cosa succede Segnale Correzione suggerita
    Query sul fornitore di contenuti lenta L'esecuzione del fornitore di contenuti richiede troppo tempo o viene bloccato. Il frame android.content.ContentProvider$Transport.query è nel thread di Binder. Ottimizza la query del fornitore di contenuti. Scopri cosa blocca il thread di Binder.
    Avvio dell'app lento L'avvio dell'app del fornitore di contenuti richiede troppo tempo. Il frame ActivityThread.handleBindApplication si trova nel thread principale. Ottimizza l'avvio dell'app.
    Esaurimento dei thread di Binder: tutti i fili di Binder sono occupati Tutti i thread di binder sono occupati a gestire altre richieste sincrone, pertanto non è possibile eseguire la chiamata a binder del fornitore di contenuti. L'app non si avvia, tutti i thread di binder sono occupati e il fornitore di contenuti non è in esecuzione. Riduci il carico sui fili di raccoglitore. Ciò significa che puoi ridurre il numero di chiamate a Binder in uscita sincrone o ridurre il lavoro di gestione delle chiamate in arrivo.

    Come eseguire il debug

    Per eseguire il debug dell'errore ANR di un fornitore di contenuti utilizzando la firma del cluster e il report ANR in Google Play Console o Firebase Crashlytics, controlla cosa stanno facendo il thread principale e i thread di Binder.

    Il seguente diagramma di flusso descrive come eseguire il debug dell'errore ANR di un fornitore di contenuti:

    Figura 7. Come eseguire il debug dell'ANR di un fornitore di contenuti.

    Il seguente snippet di codice mostra l'aspetto del thread binder quando viene bloccato a causa di una query del fornitore di contenuti lenta. In questo caso, la query del fornitore di contenuti è in attesa di blocco quando si apre 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)
    

    Lo snippet di codice riportato di seguito mostra l'aspetto del thread principale quando è bloccato a causa di un avvio lento dell'app. In questo caso, l'avvio dell'app è lento a causa della contesa del blocco durante l'inizializzazione del 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)
    

    Risposta del job lenta

    Un errore ANR di risposta lenta del job si verifica quando l'app impiega troppo tempo per rispondere a JobService.onStartJob() o JobService.onStopJob() oppure impiega troppo tempo per fornire una notifica utilizzando JobService.setNotification(). Questo suggerisce che il thread principale dell'app non esegue altre operazioni.

    Se si tratta di un problema con JobService.onStartJob() o JobService.onStopJob(), controlla cosa sta succedendo nel thread principale. Se si tratta di un problema con JobService.setNotification(), assicurati di chiamare il numero il prima possibile. Non fare molto prima di inviare la notifica.

    Errori ANR misteri

    A volte non è chiaro il motivo per cui si sta verificando un errore ANR o non sono disponibili informazioni sufficienti per eseguirne il debug nella firma del cluster e nel report ANR. In questi casi, ci sono ancora alcuni passaggi da seguire per determinare se l'ANR è applicabile.

    Coda messaggi inattiva o nativePollOnce

    Se il frame android.os.MessageQueue.nativePollOnce è presente negli stack, spesso indica che il thread sospetto che non risponde era in realtà inattivo e in attesa di messaggi looper. In Google Play Console, i dettagli ANR hanno il seguente 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 thread sospetto che non risponde può essere inattivo:

    • Dut dello stack in ritardo. Il thread si è recuperato durante il breve periodo tra l'attivazione ANR e il dump degli stack. La latenza di Pixel su Android 13 è di circa 100 ms, ma può superare 1 secondo. La latenza nei Pixel su Android 14 è solitamente inferiore a 10 ms.
    • Attribuzione errata dei thread. Il thread utilizzato per creare la firma ANR non era il thread effettivo che non risponde all'errore che ha causato l'errore ANR. In questo caso, prova a determinare se l'errore ANR è uno dei seguenti tipi:
    • Problema a livello di sistema. Il processo non è stato pianificato a causa di un carico elevato o di un problema del server di sistema.

    Nessuno stack frame

    Alcuni report ANR non includono gli stack con ANR, il che significa che il dumping dello stack non è riuscito durante la generazione del report ANR. Esistono un paio di possibili motivi per la mancanza di stack frame:

    • L'analisi della pila richiede troppo tempo e si verifica un timeout.
    • Il processo è morto o interrotto prima che i mucchi fossero presi in carico.
    [...]
    
    --- 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 utilizzabili dalla firma del cluster o dal report ANR. Per eseguire il debug, esamina altri cluster per l'app. Se un problema è abbastanza grande, di solito avrà un proprio cluster in cui sono presenti gli stack frame. Un'altra opzione è esaminare tracce Perfetto.

    Problemi noti

    Mantenere un timer nel processo dell'app al fine di terminare la gestione della trasmissione prima dell'attivazione di un ANR potrebbe non funzionare correttamente a causa del modo asincrono con cui il sistema monitora gli ANR.