2012-06-27 11 views
13

En mi onCreate() configurar un controlador uncaughtException de la siguiente manera:Cómo volver a lanzar una excepción

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable throwable) { 
     Log.e(getMethodName(2), "uncaughtException", throwable); 
     android.os.Process.killProcess(android.os.Process.myPid()); 
    } 
}); 

Funciona bien, pero me gustaría volver el comportamiento predeterminado del sistema de visualización de la fuerza- cerrar el diálogo al usuario.

Si trato de reemplazar la llamada KillProcess() con un throw throwable, el compilador se queja de que necesito rodearlo con un try/catch.

Si me rodeo con un try/catch:

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread thread, Throwable throwable) { 
     try { 
      Log.e(getMethodName(2), "uncaughtException", throwable); 
      throw throwable; 
     } 
     catch (Exception e) {   
     } 
     finally {    
     } 
    } 
}); 

El compilador se queja de que todavía queda mucho por throw throwable rodeados con un try/catch.

¿Cómo vuelvo a tirar ese arrojar? Tal que a excepción de ese informativo Log.e() el sistema se comporta exactamente como antes: Como nunca he configurado un controlador predeterminado UncaughtException.

Respuesta

18

Probar:

public class CustomExceptionHandler implements UncaughtExceptionHandler { 

    private UncaughtExceptionHandler defaultUEH; 

    public CustomExceptionHandler() { 
     this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); 
    } 

    public void uncaughtException(Thread t, Throwable e) { 
     Log.e("Tag", "uncaughtException", throwable); 
     defaultUEH.uncaughtException(t, e); 
    } 
} 

y luego Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());

Adaptado de this respuesta.

+1

Lo sentimos, pero eso da como resultado un flujo interminable de Excepciones no detectadas y ningún diálogo de cierre forzado. No es lo que estoy buscando. –

+0

He actualizado la respuesta. – Jeshurun

+0

¡Funciona muy bien! Aceptando +1. –

3

Si configura el manejador de excepciones no detectadas predeterminado, se espera que consuma la excepción en él. Esto se refleja en el hecho de que uncaughtException no declara ninguna excepción.

No debería haber ninguna razón obvia para volver a lanzarlo. Simplemente se imprimirá en el registro por segunda vez y el hilo morirá de todos modos. Si realmente quieres eso, simplemente envuelve throwable en RuntimeException y vuelve a lanzar.

+0

Entiendo y acepto que no debería haber una razón obvia para volver a lanzarlo.La única razón por la que estoy definiendo ese controlador UncaughtException predeterminado es porque no hay ** registro por primera vez! **. Entonces, si el sistema no imprime un seguimiento de pila, * I * desea imprimirlo. De ahí el controlador. Estaba muy contento con el comportamiento predeterminado del sistema, excepto por su incapacidad inexplicada para imprimir un seguimiento de la pila de esa excepción no detectada de 'android.net.http.HttpsConnection.openConnection()'. +1. –

+0

Así que lo imprimió en el controlador. ¿Por qué volver a tirar? El hilo ya está muerto ... –

2

No hay razón para volver a lanzar el Throwable, según el javadoc, it is simply ignored. El hilo termina en este punto, solo está configurando las últimas acciones que debe intentar antes de salir.

Por el bien del argumento, si se quería volver a lanzar un throwable, usted haría algo como esto:

public void reThrow(Throwable t) { 
    if (RuntimeException.class.isAssignableFrom(t.getClass())) { 
     throw (RuntimeException)t; 
    } else if (Error.class.isAssignableFrom(t.getClass())) { 
     throw (Error) t; 
    } else { 
     throw new UndeclaredThrowableException(t); 
    } 
} 
+0

+1. Ni siquiera voy a intentar volver a tirar porque estoy de acuerdo con tu afirmación (ver [mi comentario] (http://stackoverflow.com/questions/11235513/how-to-re-throw-an-exception#comment14761745_11235599) a @AlexGitelman). Aún así, sería bueno mostrar ese familiar diálogo de cierre de fuerza para el usuario. ¿Alguna idea de cómo hacerlo? –

1

en primer lugar, no es necesario volver a generar la excepción. uncaughtException() no consume la excepción. sin embargo, debe llamar al método predeterminado del manejador de excepciones no detectadas. algo así como,

class MyUEH implements UncaughtExceptionHandler { 
    private static final UncaughtExceptionHandler default = Thread.getDefaultUncaughtExceptionHandler(); 

    public void uncaughtException(Thread t, Throwable e) { 
     Log.e("Tag", "uncaughtException", throwable); 
     default.uncaughtException(t, e); 
    } 
} 

segundo, no necesita matar el proceso usted mismo. el UEH predeterminado manejará eso cuando llame a través de él.

En tercer lugar, el UEH predeterminado mostrará (o hará que se muestre) el cuadro de diálogo estándar de bloqueo (cierre forzado) para el usuario. tenga en cuenta que si su método se bloquea (porque está haciendo IO, por ejemplo), entonces el usuario no verá el diálogo de bloqueo hasta que su método finalice.

+0

Me encanta su respuesta, pero la realidad es que si comento la sentencia 'killProcess()' en la primera versión de mi controlador (dejando solo la instrucción 'Log.e()' allí, no se muestra ningún diálogo de cierre forzado y la vista de la aplicación simplemente se congela hasta que forzar manualmente el cierre de la aplicación. –

+0

sí, tienes razón. Olvidé el tidbit sobre llamar al UEH predeterminado. –

Cuestiones relacionadas