Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top