Quando a linha de execução de interface de um app Android é bloqueada por muito tempo, o sistema envia um erro "O app não está respondendo" (ANR). Esta página descreve os diferentes tipos de ANR, como diagnosticá-los e sugestões para corrigi-los. Todos os períodos de tempo limite padrão listados são para dispositivos AOSP e Pixel e podem variar de acordo com o OEM.
Ao determinar a causa dos ANRs, vale a pena distinguir entre problemas do sistema e do app.
Quando o sistema está em mau estado, os problemas abaixo podem causar ANRs:
- Problemas temporários no servidor do sistema costumam causar lentidão nas chamadas de vinculação que deveriam ser rápidas.
- Problemas com o servidor do sistema e sobrecarga do dispositivo fazem com que as linhas de execução do app não sejam agendadas.
Uma boa maneira de distinguir entre problemas do sistema e do app é usar rastros do Perfetto (link em inglês), se disponíveis:
- Confira se a linha de execução principal do app está agendada na faixa do estado da linha de execução no Perfetto para saber se ela está em execução ou pode ser executada.
- Confira se há problemas nas linhas de execução
system_server
, por exemplo, contenção de bloqueio. - Para chamadas de vinculação lentas, observe a linha de execução de resposta, se houver, para verificar por que ela está lenta.
Tempo limite do envio de entradas
ANRs de envio de entradas ocorrem quando a linha de execução principal do app não responde a tempo a um evento de entrada, por exemplo, deslizar ou pressionar uma tecla. Como o app está em primeiro plano quando o tempo limite de envio de entradas é alcançado, ele quase sempre fica visível para o usuário, e é muito importante mitigar esses problemas.
Período de tempo limite padrão: cinco segundos.
Os ANRs no envio de entradas geralmente são causados por problemas na linha de execução principal. Se a linha de execução principal estiver bloqueada enquanto espera adquirir um bloqueio, a linha de execução detentora também pode estar envolvida.
Para evitar ANRs de envio de entradas, siga estas práticas recomendadas:
- Não execute operações de bloqueio ou de longa duração na linha de execução principal. Uma opção é
usar o
StrictMode
para capturar atividades acidentais na linha de execução principal. - Minimize a contenção de bloqueio entre a linha de execução principal e as outras.
- Minimize qualquer trabalho não esteja relacionado à interface na linha de execução principal, por exemplo, ao processar transmissões ou executar serviços.
Causas comuns
Confira algumas causas comuns e correções sugeridas para ANRs de envio de entradas.
Causa | O que acontece | Correções sugeridas |
---|---|---|
Chamada de vinculação lenta | A linha de execução principal faz uma longa chamada síncrona de vinculação. | Mova a chamada para fora da linha de execução principal ou tente otimizar a chamada, se você for o proprietário da API. |
Muitas chamadas de vinculação consecutivas | A linha de execução principal faz muitas chamadas síncronas de vinculação consecutivas. | Não execute chamadas de vinculação em uma repetição curta. |
Bloqueio de E/S | A linha de execução principal faz chamadas de E/S de bloqueio, por exemplo, acesso ao banco de dados ou à rede. | Remova todas as E/S de bloqueio da linha de execução principal. |
Contenção de bloqueio | A linha de execução principal está bloqueada enquanto espera adquirir um bloqueio. | Reduza a contenção de bloqueio entre a linha de execução principal e as outras. Otimize o código lento na outra linha de execução. |
Frame caro | Renderização excessiva em um único frame, causando instabilidade grave. | Faça menos trabalho renderizando o frame. Não use algoritmos n2. Use componentes eficientes para operações como de rolagem ou paginação, por exemplo, a biblioteca Paging do Jetpack. |
Bloqueada por outro componente | Um componente diferente, por exemplo, um broadcast receiver, está em execução e bloqueando a linha de execução principal. | Remova o máximo possível de trabalhos que não sejam da interface da linha de execução principal. Execute broadcast receivers em uma linha de execução diferente. |
Suspensão de GPU | A suspensão de GPU é um problema de sistema ou hardware que faz com que a renderização seja bloqueada, causando um ANR de envio de entradas. | Em geral, não há correções a serem feitas no app nesses casos. Se possível, entre em contato com a equipe de hardware para resolver o problema. |
Como depurar
Para começar a depuração, observe a assinatura do cluster de ANR no Google Play Console ou no Firebase Crashlytics. O cluster normalmente contém os principais frames suspeitos de causar o ANR.
O fluxograma abaixo mostra como determinar a causa de um ANR de envio de tempo limite de entradas.
A execução de métricas pode detectar e ajudar a depurar algumas dessas causas comuns de ANRs. Por exemplo, se as métricas detectarem que um ANR ocorreu devido à contenção de bloqueio, elas poderão resumir o problema e a correção recomendada na seção Insights do ANR.
Nenhuma janela em foco
Embora eventos como toque sejam enviados diretamente à janela relevante com base em testes de hit, eventos como pressionamento de teclas precisam de um destino. Esse destino é conhecido como janela em foco. Há apenas uma janela em foco por tela, e geralmente é a janela com que o usuário está interagindo no momento. Se uma janela em foco não for encontrada, a entrada vai gerar um ANR de nenhuma janela em foco. Um ANR de nenhuma janela em foco é um tipo de ANR de envio de entradas.
Período de tempo limite padrão: cinco segundos.
Causas comuns
Os ANRs de nenhuma janela em foco são causados por um destes problemas:
- O app está fazendo muito trabalho e demora demais para renderizar o primeiro frame.
- Não é possível focar na janela principal. Se uma janela tiver a flag
FLAG_NOT_FOCUSABLE
, o usuário não poderá enviar eventos de tecla ou botão para ela.
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); }
Tempo limite de um broadcast receiver
Um ANR de broadcast receiver ocorre quando um broadcast receiver não processa uma
transmissão a tempo. Para broadcast receivers síncronos ou que não chamam
goAsync()
, o tempo limite significa que onReceive()
não foi concluído em um
período de dois minutos. Para receptores assíncronos ou que chamam goAsync()
, o tempo limite significa
que PendingResult.finish()
não foi chamado a tempo.
Os ANRs de broadcast receiver geralmente acontecem nestas linhas de execução:
- Linha de execução principal, se o problema for a inicialização lenta do app.
- Linha de execução que executa o broadcast receiver, se o problema for um código
onReceive()
lento. - Linhas de execução de transmissão do worker, se o problema for um código de transmissão
goAsync()
lento.
Para evitar ANRs de broadcast receiver, siga estas práticas recomendadas:
- Verifique se a inicialização do app é rápida, já que ela será contada no tempo limite do ANR se o app for iniciado para processar a transmissão.
- Se o método
goAsync()
for usado, confira sePendingResult.finish()
é chamado rapidamente. Ele está sujeito ao mesmo tempo limite de ANRs que os broadcast receivers síncronos. - Se o método
goAsync()
for usado, confira se as linhas de execução de worker não estão sendo compartilhadas com outras operações de longa duração ou bloqueio. - Uma opção é usar
registerReceiver()
para executar broadcast receivers em uma linha de execução que não seja a principal para evitar o bloqueio do código da interface executado na linha de execução principal.
Períodos de tempo limite
Os períodos de tempo limite de broadcast receiver dependem da definição da flag de intent em primeiro plano e da versão da plataforma.
Tipo de intent | Android 13 e versões anteriores | Android 14 e versões mais recentes |
---|---|---|
Intent de prioridade em primeiro plano ( |
10 segundos |
10 a 20 segundos, dependendo se o processo está com pouco acesso à CPU ou não |
Intent de prioridade de segundo plano ( |
60 segundos |
60 a 120 segundos, dependendo se o processo está com pouco acesso à CPU ou não |
Para saber se a flag FLAG_RECEIVER_FOREGROUND
está definida, procure "flg=" no conteúdo
do ANR e confira se 0x10000000
aparece. Se esse bit estiver definido, significa
que a FLAG_RECEIVER_FOREGROUND
está definida na intent, e, portanto, o tempo limite será menor.
Exemplo de conteúdo de ANR com tempo limite de transmissão curto (10 a 20 segundos):
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Exemplo de conteúdo de ANR com tempo limite de transmissão longo (60 a 120 segundos):
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Como os tempos de transmissão são medidos
A medição da duração da transmissão começa quando a transmissão é despachada do
system_server
para o app e acaba quando o app termina de processar a
transmissão. Se o processo do app ainda não estiver em execução, ele também precisará fazer uma inicialização
a frio dentro do tempo limite do ANR. Uma inicialização lenta do app pode resultar em
ANRs de broadcast receiver.
A figura abaixo ilustra o alinhamento da linha do tempo do ANR de broadcast receiver com determinados processos do app.
A medição do tempo limite do ANR acaba quando o receptor termina de processar a transmissão. O momento exato em que isso acontece depende se o receptor é síncrono ou assíncrono.
- Para receptores síncronos, a medição é interrompida quando
onReceive()
é retornado. - Para receptores assíncronos, a medição é interrompida quando
PendingResult.finish()
é chamado.
Causas comuns
Confira algumas causas comuns e correções sugeridas para ANRs de broadcast receiver.
Causa | Aplica-se a | O que aconteceu | Correção sugerida |
---|---|---|---|
Inicialização lenta do app | Todos os receptores | O app demorou muito para fazer uma inicialização a frio. | Otimize a inicialização lenta do app. |
onReceive() não agendado | Todos os receptores | A linha de execução de broadcast receiver estava ocupada fazendo outro trabalho e não pôde
iniciar o método onReceive() . | Não execute tarefas de longa duração na linha de execução receptora (ou mova o receptor para uma linha de execução dedicada). |
onReceive() lento | Todos os receptores, mas principalmente os síncronos | O método onReceive() foi iniciado, mas
estava bloqueado ou lento e não foi concluído a tempo. | Otimize o código lento do receptor. |
Tarefas de receptor assíncrono não agendadas | Receptores
goAsync() | O método onReceive() tentou executar o trabalho
em um pool de linhas de execução de worker bloqueado, então o trabalho não foi iniciado. |
Otimize chamadas lentas ou de bloqueio ou use linhas de execução diferentes para workers de transmissão em vez de outras tarefas de longa duração. |
Workers lentos ou bloqueados | Receptores goAsync() |
Ocorreu uma operação de bloqueio ou lentidão em algum lugar do pool de linhas de execução de worker
durante o processamento da transmissão, fazendo com que PendingResult.finish
não fosse chamado a tempo. | Otimize o código lento do
receptor async . |
Esqueceu de chamar PendingResult.finish |
Receptores goAsync() |
A chamada para finish() não está no caminho do código. |
finish() precisa ser chamado sempre. |
Como depurar
Com base na assinatura do cluster e no relatório de ANRs, é possível localizar a linha de execução em que o receptor é executado e, em seguida, o código específico que está ausente ou sendo executado lentamente.
O fluxograma abaixo mostra como determinar a causa de um ANR de broadcast receiver.
Encontre o código receptor
O Google Play Console mostra a classe do receptor e a intent de transmissão na assinatura do ANR. Procure o seguinte:
cmp=<receiver class>
act=<broadcast_intent>
Confira um exemplo de assinatura de ANRs de broadcast receiver:
com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }
Encontre a linha de execução do método onReceive()
Se você estiver usando Context.registerReceiver
para especificar um gerenciador personalizado,
ele será a linha de execução que executa esse gerenciador. Caso contrário, será a linha de execução principal.
Exemplo: tarefas do receptor assíncrono não agendadas
Esta seção mostra um exemplo de como depurar um ANR de broadcast receiver.
Digamos que a assinatura ANR tenha seja parecida com esta:
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
Com base na assinatura, parece que a intent de transmissão é
android.accounts.LOG_ACCOUNTS_CHANGED
e que a classe do receptor é
com.example.app.MyReceiver
.
No código do receptor, você pode determinar que o conjunto de linhas de execução "BG Thread
[0,1,2,3]" faz o trabalho principal para processar essa transmissão. Analisando os despejos
de pilha, é possível observar que todas as quatro linhas de execução em segundo plano (BG) têm o mesmo padrão:
elas executam uma chamada de bloqueio, getDataSync
. Como todas as linhas de execução em segundo plano estavam ocupadas, a
transmissão não foi processada a tempo, o que causou um 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 você não encontrar nenhuma das chamadas de função importantes, há algumas outras possibilidades:
- O serviço está em execução ou sendo encerrado, o que significa que as pilhas estão demoradas demais. Nesse caso, ignore o ANR como um falso positivo.
- Um componente de app diferente está em execução, por exemplo, um broadcast receiver. Nesse caso, a linha de execução principal provavelmente está bloqueada nesse componente, impedindo que o serviço seja iniciado.
Se você encontrar uma chamada de função principal e puder determinar onde o ANR está ocorrendo, verifique o restante das pilhas de linha de execução principais para encontrar a operação lenta e otimizá-la ou removê-la do caminho crítico.
- A inicialização do app precisa ser rápida, já que ela será contada no tempo limite do ANR se o app for iniciado para executar o provedor de conteúdo.
- As consultas do provedor de conteúdo precisam ser rápidas.
- Não execute muitas chamadas de vinculação de bloqueio simultâneas que possam bloquear todas as linhas de execução de vinculação do app.
- Despejo de pilha atrasado: A linha de execução extraída durante o curto período entre o acionamento de ANR e as pilhas que estão sendo despejadas. A latência em dispositivos Pixel com o Android 13 é de cerca de 100 ms, mas pode exceder 1 segundo. A latência em dispositivos Pixel com o Android 14 geralmente é menor que 10ms.
- Atribuição incorreta da linha de execução: A linha de execução usada para criar a assinatura de ANR não era a linha de execução não responsiva que causou o ANR. Nesse caso, tente determinar se o ANR é de um destes tipos:
- Problema do sistema: O processo não foi agendado devido a uma grande carga do sistema ou a um problema no servidor do sistema.
- A remoção da pilha demora muito e expira.
- O processo travou ou foi encerrado antes de as pilhas serem preenchidas.
Para mais informações sobre serviços, consulte estas páginas:
O provedor de conteúdo não está respondendo
Um ANR de provedor de conteúdo acontece quando um provedor de conteúdo remoto leva mais tempo do que o tempo limite para responder a uma consulta e é encerrado.
Tempo limite padrão: especificado pelo provedor de conteúdo usando
ContentProviderClient.setDetectNotResponding
. O tempo limite do ANR
inclui o tempo total de execução de uma consulta de provedor do conteúdo remoto, o que
inclui a inicialização a frio do app remoto, caso ele ainda não esteja em execução.
Para evitar ANRs do provedor de conteúdo, siga estas práticas recomendadas:
Causas comuns
A tabela abaixo lista as causas comuns de ANRs do provedor de conteúdo e as correções sugeridas.
Causa | O que acontece | Sinal | Correção sugerida |
---|---|---|---|
Consulta lenta ao provedor de conteúdo | O provedor de conteúdo demora muito para ser executado ou está bloqueado. | O frame android.content.ContentProvider$Transport.query
está na linha de execução de vinculação. |
Otimize a consulta do provedor de conteúdo. Descubra o que está bloqueando a linha de execução de vinculação. |
Inicialização lenta do app | O app do provedor de conteúdo demora muito para ser iniciado. | O frame ActivityThread.handleBindApplication está na
linha de execução principal. |
Otimize a inicialização do app. |
Esgotamento das linhas de execução de vinculação: todas as linhas de execução de vinculação estão ocupadas | Todas as linhas de execução de vinculação estão ocupadas atendendo outras solicitações síncronas. Por isso, a chamada de vinculação do provedor de conteúdo não pode ser executada. | O app não está sendo iniciado, todas as linhas de execução de vinculação estão ocupadas, e o provedor de conteúdo não está em execução. | Reduza a carga nas linhas de execução de vinculação. Ou seja, faça menos chamadas de vinculação de saída síncronas ou realize menos trabalho ao processar chamadas recebidas. |
Como depurar
Para depurar um ANR do provedor de conteúdo usando a assinatura do cluster e o Relatório de ANR no Google Play Console ou no Firebase Crashlytics, observe o que as linhas de execução principais e de vinculação estão fazendo.
O fluxograma abaixo descreve como depurar um ANR do provedor de conteúdo:
O snippet de código abaixo mostra a aparência da linha de execução de vinculação quando ela é bloqueada por uma consulta lenta do provedor de conteúdo. Nesse caso, a consulta do provedor de conteúdo está aguardando o bloqueio ao abrir um banco de dados.
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)
O snippet de código abaixo mostra a aparência da linha de execução principal quando ela é bloqueada devido à inicialização lenta do app. Nesse caso, a inicialização do app é lenta devido à contenção de bloqueio durante a inicialização do 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)
Resposta lenta ao job
Um ANR de resposta lenta de job acontece quando o app demora muito para responder a
JobService.onStartJob()
ou JobService.onStopJob()
ou demora muito para
fornecer uma notificação usando JobService.setNotification()
. Isso sugere que
a linha de execução principal do app está bloqueada fazendo alguma outra coisa.
Se for um problema com JobService.onStartJob()
ou JobService.onStopJob()
,
confira o que está acontecendo na linha de execução principal. Se for um problema com
JobService.setNotification()
, chame-o o mais rápido possível.
Não realize muito trabalho antes de enviar a notificação.
ANRs indefinidos
Às vezes, não está claro por que um ANR está ocorrendo ou não há informações suficientes para depurá-lo na assinatura do cluster e no relatório de ANR. Nesses casos, ainda há algumas etapas que podem ser seguidas para determinar se o ANR é acionável.
Fila de mensagens inativa ou nativePollOnce
Se o frame android.os.MessageQueue.nativePollOnce
é mostrado nas
pilhas, isso geralmente indica que a linha de execução suspeita não responsiva estava
inativa e aguardando mensagens de looper. No Google Play Console, os detalhes do ANR
ficam assim:
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Por exemplo, se a linha de execução principal estiver inativa, as pilhas ficarão assim:
"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)
Há vários motivos para a linha de execução suspeita não responder:
Nenhum frame de pilha
Alguns relatórios de ANR não incluem as pilhas com o ANR, o que significa que o despejo de pilha falhou ao gerar o Relatório de ANR. Há alguns motivos possíveis para a falta de frames de pilha:
[...]
--- 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 -----
[...]
ANRs sem frames de pilha não são acionáveis na assinatura do cluster ou no Relatório de ANR. Para depurar, observe outros clusters do app, já que, se um problema for grande o suficiente, ele geralmente terá o próprio cluster em que os frames de pilha estão presentes. Outra opção é analisar os rastros do Perfetto (link em inglês).
Problemas conhecidos
Manter um timer no processo do app para concluir o processamento de transmissão antes do acionamento de ANR pode não funcionar corretamente devido à forma assíncrona em que o sistema monitora ANRs.