ANR (la aplicación no responde): error que ocurre cuando la aplicación no responde. Como resultado, se abre un cuadro de diálogo que solicita al usuario que espere o cierre la aplicación.

Condiciones ANR
- Los eventos de entrada (botones y eventos táctiles) no se procesan durante 5 segundos;
- BroadcastReceiver (onRecieve ()) no se procesó dentro del tiempo especificado (primer plano - 10 s, fondo - 60 s);
- ContentProvider no se completa en 10 segundos.
Por lo general, el hilo principal está bloqueado.
Si lees mis artículos, probablemente ya estés acostumbrado al hecho de que rastreamos el código fuente. Así que veamos cómo se ve el
ANR debajo del capó .
La clase
AppErrors maneja no solo ANR, sino también otros errores que pueden ocurrir en la aplicación, incluido el bloqueo. El método handleShowAnrUi () simplemente abre esta ventana aterradora para muchos desarrolladores y usuarios que muestra ANR.
class AppErrors { ... void handleShowAnrUi(Message msg) { Dialog dialogToShow = null; synchronized (mService) { AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; final ProcessRecord proc = data.proc; if (proc == null) { Slog.e(TAG, "handleShowAnrUi: proc is null"); return; } if (proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.ALREADY_SHOWING); return; } Intent intent = new Intent("android.intent.action.ANR"); if (!mService.mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); } mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, Process.SYSTEM_UID, 0 ); boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; if (mService.canShowErrorDialogs() || showBackground) { dialogToShow = new AppNotRespondingDialog(mService, mContext, data); proc.anrDialog = dialogToShow; } else { MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR, AppNotRespondingDialog.CANT_SHOW);
Sin embargo, ANR no comienza aquí. Como dije anteriormente, una de las primeras causas de este error es el retraso del evento de entrada, que es de 5 segundos. Mediante una breve búsqueda podemos encontrar dónde se establece este valor.
namespace android {
Ahora podemos buscar en el código donde se llama la parte nativa. Esto sucede en la clase
InputManagerService .
Y aquí está el mWindowManagerCallbacks en
InputMonitor :
if (appWindowToken != null && appWindowToken.appToken != null) {
Echemos un vistazo más de cerca a inputDispatchingTimedOut (). Aquí solo mostramos el mensaje a través del ActivityManager sobre el vencimiento del tiempo de espera y dejamos que el usuario decida si cancela la acción o continúa esperando. Y es en el
ActivityManagerService que se llama AppErrors en caso de bloqueo o ANR.
private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace) { app.crashing = true; app.crashingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); startAppProblemLocked(app); app.stopFreezingAllLocked(); return handleAppCrashLocked(app, shortMsg, longMsg, stackTrace); } private void makeAppNotRespondingLocked(ProcessRecord app, String activity, String shortMsg, String longMsg) { app.notResponding = true; app.notRespondingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.NOT_RESPONDING, activity, shortMsg, longMsg, null); startAppProblemLocked(app); app.stopFreezingAllLocked(); }
Las principales causas de ANR
- Bloqueo de entrada / salida
- Congestión de red
- Hilo de bloqueo
- Bucle sin fin
- La lógica empresarial lleva demasiado tiempo
Evitar ANR
- El hilo principal de la interfaz de usuario ejecuta la lógica asociada solo con la interfaz de usuario;
- Los cálculos complejos (por ejemplo, operaciones de bases de datos, operaciones de entrada-salida, operaciones de red, etc.) se realizan en una secuencia separada;
- Use el controlador para interactuar entre el hilo de la interfaz de usuario y el flujo de trabajo;
- Use RxJava, etc. para manejar operaciones asincrónicas.
Cómo atrapar ANR
PD: publico todas las selecciones en el canal de telegramas
@paradisecurity .