15

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.

Eternal Learner
  • 2,602
  • 5
  • 27
  • 38

4 Answers4

22

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.

Community
  • 1
  • 1
Jeshurun
  • 22,940
  • 6
  • 79
  • 92
  • 2
    Sorry, but that results in endless stream of Uncaught Exceptions, and no force-close dialog at all. Not what I'm looking for. – Eternal Learner Jun 27 '12 at 22:19
5

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.

Alex Gitelman
  • 24,429
  • 7
  • 52
  • 49
  • I understand and agree that there should be no obvious reason to re-throw it. The only reason I am defining that default UncaughtException handler is because there is **no log first time!**. So if the system doesn't print a stack trace, *I* want to print it. Hence the handler. I was very happy with the system's default behavior except for its unexplained inability to print a stack trace of that uncaught exception from `android.net.http.HttpsConnection.openConnection()`. +1. – Eternal Learner Jun 27 '12 at 22:41
2

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);
    }
}
Affe
  • 47,174
  • 11
  • 83
  • 83
  • +1. I'm not even going to try re-throwing because I agree with your statement (see [my comment](http://stackoverflow.com/questions/11235513/how-to-re-throw-an-exception#comment14761745_11235599) to @AlexGitelman). Still, it would be nice to display that familiar force-close dialog to the user. Any idea how to go about this? – Eternal Learner Jun 27 '12 at 22:45
1

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.

Jeffrey Blattman
  • 22,176
  • 9
  • 79
  • 134
  • I love your answer but the reality is that if I comment out the `killProcess()` statement in the first version of my handler (leaving only the `Log.e()` statement there, no force-close dialog is displayed and the application's view simply freezes until I manually force-close the application. – Eternal Learner Jun 27 '12 at 22:51
  • yes, you are right. i forget the tidbit about calling the default UEH. – Jeffrey Blattman Jun 28 '12 at 00:17