In my onCreate() I set an UncaughtException handler as follows:
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());
}
});
It works OK, but I would like to get back the system's default behavior of displaying the force-close dialog to the user.
If I try to replace the KillProcess()
call with a throw throwable
the compiler complains that I need to surround it with a try/catch.
If I surround it with a 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 {
}
}
});
The compiler still complains that throw throwable
needs to be surrounded with a try/catch.
How do I re-throw that throwable? Such that except for that informative Log.e()
the system behaves exactly as before: As is I never set a default UncaughtException handler.
Try:
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);
}
}
and then
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());
Adapted from this answer.
If you set default uncaught exception handler, you are expected to consume the exception in it. That is reflected by the fact that uncaughtException
does not declare any exception.
There should be no obvious reason to re-throw it. It will just be printed in log second time and thread will die anyway. If you really want that, then just wrap throwable in RuntimeException
and re-throw.
There is no reason to rethrow the Throwable, as per the javadoc, it is simply ignored. The thread is terminating at this point, you're just setting up whatever last actions it's to attempt before exiting.
For the sake of argument, if you did want to rethrow a throwable, you'd do something like this:
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);
}
}
first, you don't need to re-throw the exception. uncaughtException()
does not consume the exception. you do however have to call through to the default uncaught exception handler's method. so something like,
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);
}
}
second, you don't need to kill the process yourself. the default UEH will handle that when you call through to it.
third, the default UEH will show (or cause to be shown) the standard crash (force close) dialog to the user. keep in mind that if your method hangs (because you are doing IO for example), then the user will not see the crash dialog until your method exits.