Cuando se bloquea el subproceso de IU de una app para Android durante demasiado tiempo, el sistema envía un error del tipo "Aplicación no responde" (ANR). En esta página, se describen los diferentes tipos de errores de ANR, cómo diagnosticarlos y las sugerencias para corregirlos. Todos los intervalos de tiempo de espera predeterminados que se enumeran son para dispositivos AOSP y Pixel. Estos tiempos pueden variar según el OEM.
Ten en cuenta que, cuando determines la causa de los errores de ANR, es útil distinguir entre los problemas del sistema y de la app.
Cuando el sistema está en mal estado, los siguientes problemas pueden causar errores de ANR:
- Los problemas transitorios en el servidor del sistema suele enlentecer las llamadas a Binder rápidas.
- Los problemas con el servidor del sistema y la carga alta del dispositivo hacen que no se programen los subprocesos de la app.
Si la opción está disponible, una buena manera de distinguir entre los problemas del sistema y de la app es usar los registros de Perfetto:
- Para verificar si el subproceso principal de la app está programado, observa el segmento de estado del subproceso en Perfetto para ver si se está ejecutando o puede ejecutarse.
- Observa los subprocesos de
system_server
para detectar problemas, como la contención de bloqueo. - En el caso de las llamadas a Binder lentas, observa el subproceso de respuesta (si está presente) para ver los motivos de la lentitud.
Tiempo de espera de envío de entradas
Los errores de ANR de envío de entradas se producen cuando el subproceso principal de la app no responde a tiempo a un evento de entrada, como deslizar el dedo o presionar una tecla. Dado que la app se encuentra en primer plano cuando ocurren los tiempos de espera del envío de entradas, estos casi siempre son visibles para el usuario y es muy importante mitigarlos.
Tiempo de espera predeterminado: 5 segundos
Por lo general, los errores de ANR de envío de entradas se deben a problemas en el subproceso principal. Si este subproceso principal estaba bloqueado a la espera de adquirir un bloqueo, también puede participar el subproceso contenedor.
Para evitar los errores ANR de envío de entradas, sigue estas prácticas recomendadas:
- No realices operaciones de bloqueo ni de larga duración en el subproceso principal. Te recomendamos usar
StrictMode
para detectar actividad accidental en el subproceso principal. - Minimiza la contención de bloqueo entre el subproceso principal y otros subprocesos.
- Minimiza el trabajo que no sea de IU en el subproceso principal, como cuando se manejan emisiones o se ejecutan servicios.
Causas habituales
A continuación, se indican algunas causas habituales y correcciones sugeridas para los errores de ANR en el envío de entradas.
Causa | Consecuencia | Correcciones sugeridas |
---|---|---|
Llamada a Binder lenta | El subproceso principal realiza una larga llamada síncrona a Binder. | Quita la llamada del subproceso principal o intenta optimizarla si eres el propietario de la API. |
Muchas llamadas consecutivas a Binder | El subproceso principal realiza muchas llamadas consecutivas a Binder síncronas. | No realices llamadas a Binder en un bucle cerrado. |
Bloqueo de E/S | El subproceso principal realiza un bloqueo de llamadas de E/S, como el acceso a la base de datos o a la red. | Quita todo el E/S de bloqueo del subproceso principal. |
Contención de bloqueo | El subproceso principal está bloqueado a la espera de adquirir un bloqueo. | Reduce la contención de bloqueo entre el subproceso principal y otro. Optimiza el código lento en el otro subproceso. |
Fotograma costoso | Demasiada renderización en un solo fotograma, lo que provoca bloqueos graves. | Haz menos trabajo renderizando el fotograma. No uses algoritmos n2. Usa componentes eficientes para elementos como el desplazamiento o la paginación, por ejemplo, la biblioteca de Paging de Jetpack. |
Bloqueo de otro componente | Un componente diferente, como un receptor de emisión, está ejecutando y bloqueando el subproceso principal. | Quita el trabajo que no sea de IU del subproceso principal tanto como sea posible. Ejecuta los receptores de emisión en un subproceso diferente. |
Bloqueo de GPU | El bloqueo de la GPU es un problema del sistema o de hardware que hace que se bloquee la renderización y, por lo tanto, se genere un error de ANR de envío de entradas. | Lamentablemente, no suele haber correcciones del lado de la app. Si es posible, comunícate con el equipo de hardware para solucionar el problema. |
Cómo hacer la depuración
Para comenzar la depuración, consulta la firma del clúster de ANR en Google Play Console o Firebase Crashlytics. Por lo general, el clúster contiene los fotogramas principales que se sospecha que causan el error de ANR.
En el siguiente diagrama de flujo, se muestra cómo determinar la causa de un error de ANR de envío de tiempo de espera de entradas.
Play Vitals puede detectar algunas de estas causas comunes de errores de ANR y ayudar a depurarlas. Por ejemplo, si Vitals detecta que se produjo un error de ANR debido a la contención de bloqueo, puedes resumir el problema y recomendar la corrección en la sección Estadísticas de ANR.
No hay ventanas enfocadas
Si bien los eventos como los toques se envían directamente a la ventana relevante según la prueba de posicionamiento, los eventos como las teclas necesitan un destino. Este destino se conoce como la ventana enfocada. Solo hay una ventana enfocada por pantalla y, por lo general, es con la que el usuario está interactuando en ese momento. Si no se puede encontrar una ventana enfocada, la entrada genera un error de ANR de ventana no enfocada. Un error de ANR de ventana no enfocada es un tipo de ANR de envío de entradas.
Tiempo de espera predeterminado: 5 segundos
Causas habituales
Por lo general, los errores de ANR de ventana no enfocada se deben a cualquiera de los siguientes problemas:
- La app realiza demasiado trabajo y es demasiado lenta para dibujar el primer fotograma.
- La ventana principal no es enfocable. Si una ventana está marcada con un objeto
FLAG_NOT_FOCUSABLE
, el usuario no puede enviarle eventos de teclas ni de botones.
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); }
Tiempo de espera del receptor de emisión
Un error de ANR de receptor de emisión se produce cuando un receptor de emisión no controla una transmisión a tiempo. En el caso de los receptores síncronos o de los que no llaman a goAsync()
, un tiempo de espera significa que onReceive()
no se completó a tiempo. En el caso de los receptores asíncronos o de los que llaman a goAsync()
, un tiempo de espera significa que PendingResult.finish()
no se llamó a tiempo.
Los errores de ANR del receptor de emisión suelen ocurrir en estos subprocesos:
- Subproceso principal, si el problema es un inicio lento de la app
- Receptor de emisión de subproceso en ejecución, si el problema es un código
onReceive()
lento - Subprocesos de trabajo de transmisión, si el problema es el código de transmisión
goAsync()
lento
Para evitar los errores de ANR del receptor de emisión, sigue estas prácticas recomendadas:
- Asegúrate de que el inicio de la app sea rápido, ya que se cuenta en el tiempo de espera de ANR si la app se inicia para controlar la transmisión.
- Si se usa
goAsync()
, asegúrate de que se llame aPendingResult.finish()
rápidamente. Esto está sujeto al mismo tiempo de espera de ANR que los receptores de emisión síncronos. - Si se usa
goAsync()
, asegúrate de que los subprocesos de trabajo no se compartan con otras operaciones de bloqueo o de larga duración. - Considera usar
registerReceiver()
para ejecutar receptores de emisión en un subproceso que no sea el principal para evitar el bloqueo del código de la IU que se ejecuta en el subproceso principal.
Períodos de tiempo de espera
Los períodos de tiempo de espera de recepción de emisión dependen de si se configuró la marca de intent en primer plano y de la versión de la plataforma.
Tipo de intent | Android 13 y versiones anteriores | Android 14 y versiones posteriores |
---|---|---|
Intent de prioridad en primer plano ( |
10 segundos |
Entre 10 y 20 segundos, dependiendo de si el proceso se queda sin CPU |
Intent de prioridad en segundo plano ( |
60 segundos |
Entre 60 y 120 segundos, dependiendo de si el proceso se queda sin CPU |
Para saber si se configuró la marca FLAG_RECEIVER_FOREGROUND
, busca "flg=" en el asunto de ANR y comprueba la presencia de 0x10000000
. Si se configura este bit, entonces se configuró FLAG_RECEIVER_FOREGROUND
en el intent, y, por lo tanto, el tiempo de espera es más corto.
Ejemplo de asunto de ANR con tiempo de espera de transmisión corto (10 a 20 segundos):
Broadcast of Intent { act=android.inent.action.SCREEN_ON flg=0x50200010 }
Ejemplo de asunto de ANR con tiempo de espera de transmisión largo (60 a 120 segundos):
Broadcast of Intent { act=android.intent.action.TIME_SET flg=0x25200010 }
Cómo se miden los tiempos de transmisión
La medición de la duración de la transmisión comienza cuando la transmisión se envía de system_server
a la app y finaliza cuando esta termina de procesarla. Si el proceso de la app aún no se estaba ejecutando, también debe realizar un inicio en frío dentro del período de tiempo de espera del error de ANR. Por lo tanto, un inicio lento de la app puede generar errores de ANR del receptor de emisión.
En la siguiente figura, se ilustra que el cronograma de ANR del receptor de emisión se alinea con ciertos procesos de la app.
La medición del tiempo de espera de ANR finaliza cuando el receptor termina de procesar la transmisión. El momento exacto en que esto sucede depende de si se trata de un receptor síncrono o asíncrono.
- En el caso de los receptores síncronos, la medición se detiene cuando se devuelve
onReceive()
. - En el caso de los receptores asíncronos, la medición se detiene cuando se llama a
PendingResult.finish()
.
Causas habituales
A continuación, se indican algunas causas habituales y correcciones sugeridas para los errores de ANR del receptor de emisión.
Causa | Se aplica a | ¿Qué sucedió? | Corrección sugerida |
---|---|---|---|
Inicio lento de la app | Todos los receptores | La app tardó demasiado en iniciarse en frío. | Optimiza el inicio lento de la app. |
No se programó onReceive() | Todos los receptores | El subproceso del receptor de emisión estaba ocupado realizando otro trabajo y no pudo iniciar el método onReceive() . | No realices tareas de larga duración en el subproceso del receptor (ni muevas el receptor al subproceso dedicado). |
onReceive() tiene un funcionamiento lento | Todos los receptores, pero principalmente los síncronos | Se inició el método onReceive() , pero estaba bloqueado o lento, por lo que no se completó a tiempo. | Optimiza el código del receptor lento. |
No se programaron tareas del receptor asíncrono | Receptores de goAsync() | El método onReceive() intentó ejecutar trabajos en un grupo de subprocesos de trabajo bloqueados, por lo que nunca se inició el trabajo. |
Optimiza las llamadas lentas o de bloqueo, o usa diferentes subprocesos para los trabajadores de transmisión en comparación con otras tareas de larga duración. |
Los trabajadores son lentos o están bloqueados | Receptores de goAsync() |
Hubo una operación de bloqueo o lenta en algún lugar del grupo de subprocesos de trabajo mientras se procesaba la transmisión. Por lo tanto, no se llamó a PendingResult.finish a tiempo. | Optimiza el código del receptor async lento. |
Olvidaste llamar a PendingResult.finish . |
Receptores de goAsync() |
Falta la llamada a finish() en las instrucciones de código. |
Asegúrate de que siempre se llame a finish() . |
Cómo hacer la depuración
Según la firma del clúster y el informe de ANR, puedes ubicar el subproceso en el que se ejecuta el receptor y, luego, el código específico que falta o que se ejecuta con lentitud.
En el siguiente diagrama de flujo, se muestra cómo determinar la causa de un error de ANR del receptor de emisión.
Cómo buscar el código del receptor
Google Play Console muestra la clase del receptor y el intent de transmisión en la firma de ANR. Busca lo siguiente:
cmp=<receiver class>
act=<broadcast_intent>
Este es un ejemplo de una firma de ANR de receptor de emisión:
com.example.app.MyClass.myMethod
Broadcast of Intent { act=android.accounts.LOGIN_ACCOUNTS_CHANGED
cmp=com.example.app/com.example.app.MyAccountReceiver }
Cómo buscar el subproceso que ejecuta el método onReceive()
Si usas Context.registerReceiver
para especificar un controlador personalizado, el subproceso es el que ejecuta el controlador. De lo contrario, es el subproceso principal.
Ejemplo: No se programaron tareas asíncronas del receptor
En esta sección, se muestra un ejemplo de cómo depurar un error de ANR del receptor de emisión.
Supongamos que la firma de ANR se parece a lo siguiente:
com.example.app.MyClass.myMethod
Broadcast of Intent {
act=android.accounts.LOG_ACCOUNTS_CHANGED cmp=com.example.app/com.example.app.MyReceiver }
Según la firma, parece que el intent de transmisión es android.accounts.LOG_ACCOUNTS_CHANGED
y la clase del receptor es com.example.app.MyReceiver
.
A partir del código del receptor, puedes determinar que el grupo de subprocesos "BG Thread [0,1,2,3]" realiza el trabajo principal para procesar esta transmisión. Si observas los volcados de pila, puedes ver que los cuatro subprocesos en segundo plano (BG) tienen el mismo patrón: ejecutan una llamada de bloqueo, getDataSync
. Como todos los subprocesos de BG estaban ocupados, la transmisión no se pudo procesar a tiempo, lo que generó un error de 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)
Si no puedes ver ninguna de las llamadas importantes a funciones, existen otras posibilidades:
- El servicio se está ejecutando o cerrando, lo que significa que las pilas se usan demasiado tarde. En este caso, puedes ignorar el error de ANR y considerarlo un falso positivo.
- Se está ejecutando un componente de app diferente, como un receptor de emisión. En este caso, es probable que el subproceso principal esté bloqueado en este componente, lo que evita que se inicie el servicio.
Si ves una llamada a una función clave y puedes determinar dónde ocurre generalmente el error de ANR, verifica el resto de las pilas de subprocesos principales para detectar la operación lenta y optimizarla o quitarla de la ruta crítica.
- Asegúrate de que el inicio de la app sea rápido, ya que se cuenta en el tiempo de espera de ANR si la app se inicia para ejecutar el proveedor de contenido.
- Asegúrate de que las consultas del proveedor de contenido sean rápidas.
- No realices muchas llamadas simultáneas de Binder de bloqueo que puedan bloquear todos los subprocesos de Binder de la app.
- Volcado tardío de la pila: El subproceso recuperado durante el corto período entre la activación del error de ANR y las pilas que se vuelcan. En Android 13, la latencia en píxeles es de alrededor de 100 ms, pero puede exceder 1 s. En Android 14, la latencia en píxeles suele ser inferior a 10 ms.
- Atribución incorrecta del subproceso: El subproceso que se usó para compilar la firma de ANR no fue el subproceso real que no respondió y que lo causó. En este caso, intenta determinar si el error de ANR es uno de los siguientes:
- Problema en todo el sistema: El proceso no se programó debido a una carga pesada del sistema o un problema en su servidor.
- Tomar la pila lleva demasiado tiempo y se agota el tiempo de espera.
- El proceso finalizó o se eliminó antes de que se tomaran las pilas.
Para obtener más información sobre los servicios, consulta las siguientes páginas:
El proveedor de contenido no responde
Un error de ANR de proveedor de contenido se produce cuando un proveedor de contenido remoto tarda más que el tiempo de espera en responder a una consulta y se cierra.
Tiempo de espera predeterminado: El proveedor de contenido lo especifica con ContentProviderClient.setDetectNotResponding
. El tiempo de espera de ANR incluye el tiempo total que tarda en ejecutarse una consulta al proveedor de contenido remoto, que incluye el inicio en frío de la app remota si aún no se estaba ejecutando.
Para evitar los errores ANR del proveedor de contenido, sigue estas prácticas recomendadas:
Causas habituales
En la siguiente tabla, se enumeran las causas habituales de los errores de ANR del proveedor de contenido y las correcciones sugeridas.
Causa | Consecuencia | Señal | Corrección sugerida |
---|---|---|---|
Consulta lenta al proveedor de contenido | El proveedor de contenido tarda demasiado en ejecutarse o está bloqueado. | El marco android.content.ContentProvider$Transport.query está en el subproceso de Binder. |
Optimiza la consulta al proveedor de contenido. Descubre qué bloquea el subproceso Binder. |
Inicio lento de la app | La app del proveedor de contenido tarda demasiado en iniciarse. | El marco ActivityThread.handleBindApplication se encuentra en el subproceso principal. |
Optimiza el inicio de la app. |
Agotamiento del subproceso de Binder (todos los subprocesos de Binder están ocupados) | Todos los subprocesos de Binder están ocupados entregando otras solicitudes síncronas, por lo que no se puede ejecutar la llamada a Binder del proveedor de contenido. | La app no se inicia, todos los subprocesos de Binder están ocupados y el proveedor de contenido no se está ejecutando. | Reduce la carga en subprocesos de Binder. Es decir, realiza menos llamadas síncronas de Binder salientes o haz menos trabajo cuando se administran las llamadas entrantes. |
Cómo hacer la depuración
Para depurar un ANR de proveedor de contenido con la firma del clúster y el informe de ANR en Google Play Console o Firebase Crashlytics, observa lo que hacen el subproceso principal y los de Binder.
En el siguiente diagrama de flujo, se describe cómo depurar un ANR de proveedor de contenido:
En el siguiente fragmento de código, se muestra cómo se ve el subproceso de Binder cuando está bloqueado debido a una consulta lenta al proveedor de contenido. En este caso, la consulta al proveedor de contenido espera el bloqueo cuando abre una base de datos.
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)
En el siguiente fragmento de código, se muestra cómo se ve el subproceso principal cuando se bloquea debido a un inicio lento de la app. En este caso, el inicio de la app es lento debido a la contención de bloqueos durante la inicialización de Dagger.
main (tid=1) Blocked
[...]
at dagger.internal.DoubleCheck.get(DoubleCheck:51)
- locked 0x0e33cd2c (a qsn)at dagger.internal.SetFactory.get(SetFactory:126)
at com.myapp.Bar_Factory.get(Bar_Factory:38)
[...]
at com.example.app.MyApplication.onCreate(DocsApplication:203)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1316)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:6991)
at android.app.ActivityThread.-$$Nest$mhandleBindApplication(unavailable:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2235)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:205)
at android.os.Looper.loop(Looper.java:294)
at android.app.ActivityThread.main(ActivityThread.java:8170)
at java.lang.reflect.Method.invoke(Native method:0)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Respuesta de trabajo lenta
Un error de ANR de respuesta de trabajo lenta ocurre cuando la app tarda demasiado en responder a JobService.onStartJob()
o JobService.onStopJob()
, o tarda demasiado en proporcionar una notificación con JobService.setNotification()
. Esto sugiere que el subproceso principal de la app está bloqueado para realizar otra acción.
Si es un problema con JobService.onStartJob()
o JobService.onStopJob()
, verifica lo que sucede en el subproceso principal. Si es un problema con JobService.setNotification()
, asegúrate de realizar la llamada lo más rápido posible.
No hagas mucho trabajo antes de proporcionar la notificación.
Errores de ANR misteriosos
A veces, no está claro el motivo por el que se produce un error de ANR o no hay información suficiente para depurarlo en la firma del clúster ni el informe de ANR. En estos casos, aún puedes seguir algunos pasos para determinar se pueden realizar acciones en el error de ANR.
La cola de mensajes está inactiva o nativePollOnce
Si ves el marco android.os.MessageQueue.nativePollOnce
en las pilas, a menudo significa que el subproceso que parecía no responder, en realidad, estaba inactivo y a la espera de mensajes del generador de bucles. En Google Play Console, los detalles del error de ANR tienen el siguiente aspecto:
Native method - android.os.MessageQueue.nativePollOnce
Executing service com.example.app/com.example.app.MyService
Por ejemplo, si el subproceso principal está inactivo, las pilas se ven así:
"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)
Hay varios motivos por los que el subproceso que parece no responder puede estar inactivo:
Sin marcos de pila
Algunos informes de ANR no incluyen las pilas con el error de ANR, lo que significa que el volcado de pila falló cuando se generaba el informe de ANR. Existen dos motivos posibles por los que faltan marcos de pila:
[...]
--- 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 -----
[...]
No se pueden realizar acciones en los errores de ANR sin marcos de pila desde la firma del clúster ni el informe de ANR. Para depurar, observa otros clústeres de la app, ya que, si un problema es lo suficientemente grande, por lo general, tendrá su propio clúster en el que están presentes los marcos de pila. Otra opción es consultar los registros de Perfetto.
Errores conocidos
Es posible que mantener un temporizador en el proceso de tu app con el fin de finalizar el manejo de la transmisión antes de que se active un error de ANR no funcione correctamente debido a la forma asíncrona en que el sistema supervisa los errores de ANR.