ANR (Application Not Responding) es una notificación del sistema Android que aparece cuando una aplicación deja de responder a la entrada del usuario durante más de 5 segundos. Según Android Developers, la causa principal son las operaciones largas en el hilo principal que bloquean el procesamiento de toques y el renderizado de la interfaz. Comprender los mecanismos de ANR es esencial para todo desarrollador Android que quiera crear aplicaciones receptivas.
Puntos clave
ANR (Application Not Responding) es un cuadro de diálogo del sistema operativo Android que aparece cuando una aplicación deja de responder a la entrada del usuario. El sistema rastrea el tiempo de procesamiento de eventos a través de InputDispatcher: si un toque o la presión de un botón no se maneja en 5 segundos, Android muestra un diálogo ofreciendo cerrar o esperar la aplicación.
El mecanismo ANR protege la experiencia del usuario de aplicaciones congeladas. Android no permite que una aplicación bloquee todo el sistema — a diferencia de los sistemas operativos de escritorio, la plataforma móvil limita forzosamente el tiempo de procesamiento de eventos. BroadcastReceiver tiene un límite de 10 segundos, y un servicio en primer plano tiene 20 segundos.
ANR NO es una excepción en el código — es un mecanismo del sistema a nivel de procesos de Linux. Android envía una señal SIGQUIT al proceso, tras lo cual el sistema guarda la pila de llamadas de todos los hilos en el archivo traces.txt. El desarrollador no recibe ANR como una excepción catch, sino como un informe tras el reinicio de la aplicación. En Android 11+, la API ApplicationExitInfo permite obtener programáticamente la razón de la terminación del proceso, incluido ANR — esto simplifica la recopilación de estadísticas sin necesidad de analizar manualmente traces.txt.
Cinco categorías de operaciones conducen constantemente a ANR en aplicaciones Android. Cada una de ellas bloquea el hilo principal, impidiendo que el sistema procese eventos de entrada y el redibujado de la pantalla.
Las peticiones HTTP síncronas ejecutadas en el hilo de UI son la causa más común de ANR entre los desarrolladores principiantes. Incluso una petición rápida a un servidor puede tomar 1–3 segundos, y con una conexión deficiente — 30 segundos o más. Android prohíbe explícitamente las operaciones de red en el hilo principal a partir de la API 11, lanzando NetworkOnMainThreadException.
Use Coroutines o RxJava para llamadas asíncronas. Las corrutinas con el dispatcher Dispatchers.IO ejecutan la petición en un hilo de fondo y pasan el resultado al hilo principal mediante Dispatchers.Main. Esto elimina por completo el bloqueo del hilo de UI por operaciones de red.
fun fetchUserData() {
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.IO) {
api.getUserData() // operación en segundo plano
}
updateUI(result) // resultado en el hilo principal
}
}
Procesar grandes arrays de datos, analizar JSON o XML, trabajar con bitmaps directamente en el hilo principal — la segunda causa más frecuente de ANR. Incluso 300 milisegundos de trabajo continuo del hilo de UI sin volver al bucle de eventos causa un retraso notable en el renderizado, y el umbral de 5 segundos se registra como ANR.
WorkManager y los servicios en segundo plano están diseñados para mover los cálculos pesados fuera del hilo principal. Use AsyncTask (obsoleto), ListenableFuture o Kotlin Flow para pasar datos en fragmentos sin bloquear la UI.
Un Deadlock ocurre cuando dos hilos mantienen bloqueos y esperan el uno al otro. Si uno de los hilos es el hilo principal, el sistema registra ANR exactamente después de 5 segundos. Thread.join(), CountDownLatch.await() y los bloques synchronized llamados desde el hilo de UI conllevan riesgo de bloqueo.
Evite cualquier operación bloqueante en el hilo principal. En lugar de synchronized, use ConcurrentHashMap; en lugar de Thread.join() — corrutinas con async/await. Esta regla se aplica a cualquier lenguaje en Android: Java, Kotlin o C++ mediante JNI.
BroadcastReceiver se ejecuta en el hilo principal por defecto. Si onReceive() está ocupado durante más de 10 segundos, Android muestra ANR. Cargar datos desde una base de datos o red dentro de onReceive es un camino garantizado hacia la congelación.
Use goAsync() dentro de BroadcastReceiver para cambiar a un hilo de fondo, o registerReceiver con getBackgroundBroadcastReceiver(). Esto permite manejar eventos sin bloquear la UI.
Las consultas pesadas a ContentProvider o el trabajo directo con SQLite en el hilo de UI — una causa menos obvia pero común de ANR. Durante la migración de la base de datos o la inserción masiva de miles de registros, el tiempo de ejecución puede superar el límite de 5 segundos.
Mueva todas las operaciones de base de datos a hilos de fondo usando Room con funciones suspend. Room comprueba automáticamente que la consulta no se ejecuta en el hilo principal y lanza una excepción si se viola.
Diagnosticar ANR difiere de depurar excepciones normales — no se puede capturar ANR en un bloque try-catch. La principal fuente de información es el archivo traces.txt, que Android crea en el momento de la congelación.
traces.txt contiene la pila de llamadas de todos los hilos de la aplicación en el momento del ANR. Para leer el archivo desde un dispositivo real, ejecute el comando adb bugreport, que recopila un informe completo del sistema incluyendo todos los ANR recientes. Para un emulador, el archivo está disponible en /data/anr/traces.txt. La pila de llamadas muestra qué método se estaba ejecutando en el hilo principal en el momento del bloqueo.
adb bugreport bugreport.zip
unzip -p bugreport.zip "*traces*" > traces.txt
Google Play Console proporciona la sección ANR & Crash con informes agregados y frecuencias de error. Para cada ANR, se muestra la pila de llamadas y estadísticas del dispositivo: modelo, versión de Android, región. Esto permite identificar ANR que dependen de dispositivos o versiones del sistema específicos.
Android Studio desde 2021 incluye ANR Watchdog en el perfilador. Graba automáticamente volcados de hilos si el hilo principal no responde durante más de un tiempo umbral. La herramienta muestra una línea de tiempo de eventos: qué operaciones se iniciaron, qué métodos se ejecutaron y en qué etapa ocurrió el bloqueo.
La prevención de ANR se basa en una regla fundamental: el hilo principal solo debe manejar eventos de UI. Cualquier operación de más de 16 milisegundos (tiempo de un fotograma) debe ejecutarse en un hilo de fondo.
StrictMode es una herramienta integrada de Android para detectar posibles ANR durante el desarrollo. Actívelo en Application.onCreate() con banderas para operaciones de disco y red. Cuando se viola, StrictMode lanza una excepción o escribe en logcat.
if (BuildConfig.DEBUG) {
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build()
.let { StrictMode.setThreadPolicy(it) }
}
Kotlin Coroutines — la forma estándar de trabajo asíncrono en aplicaciones Android modernas. El enfoque principal: las operaciones de E/S se ejecutan en Dispatchers.IO, el resultado se pasa a Dispatchers.Main para actualizaciones de UI. Para escenarios similares a Flow, use Dispatchers.Default para tareas intensivas de CPU.
RxJava sigue siendo popular en proyectos heredados. subscribeOn(Schedulers.io()) y observeOn(AndroidSchedulers.mainThread()) — el conjunto mínimo para prevenir ANR. La regla principal es la misma: ningún Observable o Flowable debe emitir datos desde el hilo principal.
Firebase Crashlytics desde la versión SDK 18.4.0 admite monitoreo de ANR de forma nativa. Para Android 11+, Crashlytics usa la API del sistema ApplicationExitInfo, que proporciona la razón exacta de la terminación: ANR, Crash, o eliminación por el sistema. Active claves personalizadas con parámetros de pantalla y estado para análisis contextual.
Cinco herramientas cubren todas las etapas del trabajo con ANR: desde la depuración en una estación de trabajo hasta el monitoreo en producción. Cada herramienta resuelve su propia tarea y proporciona datos para diferentes escenarios.
| Herramienta | Propósito | Formato de datos |
|---|---|---|
| StrictMode | Detección durante el desarrollo | Logcat / Exception |
| ANR Watchdog (Android Studio) | Seguimiento en tiempo real | Thread dump + timeline |
| Google Play Console | Estadísticas agregadas | ANR rate + stack traces |
| Firebase Crashlytics | Monitoreo en producción | ApplicationExitInfo |
| adb bugreport | Informe completo del sistema | traces.txt + logcat + dmesg |
Cada herramienta tiene su propio nicho: StrictMode detecta violaciones obvias en etapas tempranas, Crashlytics muestra la frecuencia real de ANR entre los usuarios, y adb bugreport proporciona la imagen más completa para casos complejos. Combínelas para una cobertura total.
Firebase Performance rastrea el tiempo de respuesta del hilo de UI y crea automáticamente seguimientos para operaciones sospechosamente largas. Si el hilo principal se bloquea durante más de 500 ms, Performance registra un seguimiento personalizado con el nombre del método culpable. Esto permite detectar escenarios de ANR sin intervención del usuario y antes de que se vuelvan críticos.
La integración con Firebase Crashlytics proporciona una imagen completa: Performance muestra las ralentizaciones antes del ANR, y Crashlytics muestra la congelación misma. Configure alertas en Firebase Console para una tasa de ANR superior al 0.1%, y recibirá notificaciones sobre nuevos problemas antes de quejas masivas de usuarios.
Preguntas frecuentes
ANR es una congelación en la que la aplicación no responde pero permanece en memoria. Crash es una terminación anormal completa con salida del proceso. ANR puede “sobrevivirse” si el sistema o el usuario esperan una respuesta, mientras que Crash siempre termina la aplicación.
No. ANR no es una excepción de Java/Kotlin, sino una señal del sistema a nivel de procesos (SIGQUIT). Un desarrollador no puede manejarlo en el código de la aplicación. La única forma de responder a ANR es analizar los informes después del reinicio.
El rendimiento del dispositivo, la versión de Android, la carga de CPU y la cantidad de procesos en segundo plano afectan la probabilidad de ANR. En dispositivos débiles, la misma operación puede tomar de 2 a 3 veces más tiempo, superando el límite de 5 segundos.
10 segundos para un BroadcastReceiver normal en onReceive(). Para servicios en primer plano, el límite es de 20 segundos, y para ContentProvider — no hay un límite explícito, pero bloquear el hilo principal durante más de 5 segundos aún provoca ANR.
Active StrictMode en todas las compilaciones de depuración, agregue monitoreo mediante Firebase Crashlytics y use adb bugreport cuando ocurra ANR. Los ANR irregulares a menudo están relacionados con condiciones de carrera o estados de red específicos.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también