Quiero establecer un controlador de excepciones no detectado global para todos los subprocesos en mi aplicación de Android. Entonces, en mi Application
subclase configuré una implementación de Thread.UncaughtExceptionHandler
como controlador predeterminado para excepciones no detectadas.
Thread.setDefaultUncaughtExceptionHandler(
new DefaultExceptionHandler(this));
En mi implementación, estoy tratando de mostrar un AlertDialog
mensaje de excepción apropiado.
Sin embargo, esto no parece funcionar. Siempre que se lanza una excepción para cualquier hilo que no se maneja, aparece el cuadro de diálogo predeterminado del sistema operativo ("¡Lo siento! -La aplicación se ha detenido inesperadamente").
¿Cuál es la forma correcta e ideal de establecer un controlador predeterminado para las excepciones no detectadas?
Respuestas:
Eso debería ser todo lo que necesita hacer. (Asegúrese de hacer que el proceso se detenga después; las cosas podrían estar en un estado incierto).
Lo primero que hay que comprobar es si todavía se está llamando al controlador de Android. Es posible que su versión esté siendo llamada pero fallando fatalmente y system_server esté mostrando un diálogo genérico cuando ve que el proceso falla.
Agregue algunos mensajes de registro en la parte superior de su controlador para ver si está llegando. Imprima el resultado de getDefaultUncaughtExceptionHandler y luego lance una excepción no detectada para provocar un bloqueo. Esté atento a la salida de logcat para ver qué está pasando.
fuente
Publiqué la solución simple para el manejo personalizado de fallas de Android hace mucho tiempo. Es un poco hacky, sin embargo, funciona en todas las versiones de Android (incluido el Lollipop).
Primero un poco de teoría. Los principales problemas cuando usa un controlador de excepciones no detectado en Android vienen con las excepciones lanzadas en el hilo principal (también conocido como UI). Y he aquí por qué. Cuando la aplicación inicia el sistema llama al método ActivityThread.main que prepara e inicia el bucle principal de su aplicación:
public static void main(String[] args) { … … Looper.prepareMainLooper(); … Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
El looper principal es responsable de procesar los mensajes publicados en el hilo de la interfaz de usuario (incluidos todos los mensajes relacionados con la representación e interacción de la interfaz de usuario). Si se lanza una excepción en el hilo de la interfaz de usuario, su controlador de excepciones la detectará, pero como no tiene
loop()
método, no podrá mostrar ningún diálogo o actividad al usuario, ya que no queda nadie para procesar los mensajes de la interfaz de usuario para ti.La solución propuesta es bastante sencilla. Ejecutamos el
Looper.loop
método por nuestra cuenta y lo rodeamos con el bloque try-catch. Cuando se detecta una excepción, la procesamos como queremos (por ejemplo, iniciamos nuestra actividad de informe personalizado) y volvemos a llamar alLooper.loop
método.El siguiente método demuestra esta técnica (debe llamarse desde el
Application.onCreate
oyente):private void startCatcher() { UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler(); // the following handler is used to catch exceptions thrown in background threads Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler(new Handler())); while (true) { try { Looper.loop(); Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler); throw new RuntimeException("Main thread loop unexpectedly exited"); } catch (Throwable e) { showCrashDisplayActivity(e); } } }
Como puede ver, el controlador de excepciones no detectado se usa solo para las excepciones lanzadas en subprocesos en segundo plano. El siguiente controlador detecta esas excepciones y las propaga al hilo de la interfaz de usuario:
static class UncaughtHandler implements UncaughtExceptionHandler { private final Handler mHandler; UncaughtHandler(Handler handler) { mHandler = handler; } public void uncaughtException(Thread thread, final Throwable e) { mHandler.post(new Runnable() { public void run() { throw new BackgroundException(e); } }); } }
Un proyecto de ejemplo que utiliza esta técnica está disponible en mi repositorio de GitHub: https://github.com/idolon-github/android-crash-catcher
fuente
java.lang.RuntimeException: Performing pause of activity that is not resumed
. Creo que cuando intento iniciar mi propio bucleador, el sistema detiene la actividad que está a punto de comenzar. No estoy seguro, pero se agradecería cualquier ayuda. GraciasCreo que para deshabilitar eso en su método uncaughtException () no llame a previousHandler.uncaughtException () donde previousHandler está configurado por
previousHandler = Thread.getDefaultUncaughtExceptionHandler();
fuente
FWIW Sé que esto está un poco fuera de tema, pero hemos estado usando el plan gratuito de Crittercism con éxito. También ofrecen algunas funciones premium, como manejar la excepción para que la aplicación no se bloquee.
En la versión gratuita, el usuario aún ve el bloqueo, pero al menos recibo el correo electrónico y el seguimiento de la pila.
También usamos la versión de iOS (pero mis colegas me han dicho que no es tan buena).
Aquí hay preguntas similares:
fuente
No funciona hasta que llamas
android.os.Process.killProcess(android.os.Process.myPid());
al final de su UncaughtExceptionHandler.
fuente