ChatGPT解决这个技术问题 Extra ChatGPT

Ideal way to set global uncaught exception Handler in Android

I want to set a global uncaught exception handler for all the threads in my Android application. So, in my Application subclass I set an implementation of Thread.UncaughtExceptionHandler as default handler for uncaught exceptions.

Thread.setDefaultUncaughtExceptionHandler(
                new DefaultExceptionHandler(this));

In my implementation, I am trying to display an AlertDialog displaying appropriate exception message.

However, this doesn't seem to work. Whenever, an exception is thrown for any thread which goes un-handled, I get the stock, OS-default dialog ("Sorry!-Application-has-stopped-unexpectedly dialog").

What is the correct and ideal way to set a default handler for uncaught exceptions?

Can you please share the code for the same ...
If you wish to log your exceptions, have a look at acra.ch. ACRA allows you to send error-reports to a Google-Doc or to you via E-Mail.
@Alexander Or you can just use Google Analytics for Android, and log all the exceptions you want...

f
fadden

That should be all you need to do. (Make sure you cause the process to halt afterward -- things could be in an uncertain state.)

The first thing to check is whether the Android handler is still getting called. It's possible that your version is being called but failing fatally and the system_server is showing a generic dialog when it sees the process crash.

Add some log messages at the top of your handler to see if it's getting there. Print the result from getDefaultUncaughtExceptionHandler and then throw an uncaught exception to cause a crash. Keep an eye on the logcat output to see what's going on.


"throwing an uncaught exception to cause a crash after you handled the error" is still important. I just experienced it. My app got locked after I handled the exception and did not throw an uncaught exception.
@OneWorld Jepp same here - at least for the locking part - there seems to be no way to "save" the app from crashing after all.
@Zainodis I posted a mildly off-topic answer to this question giving a link to Crittercism - I think they have a feature that allows you to "save" the app from crashing after all. Not sure - I am only using the free version atm.
@RichardLeMesurier Thanks for the hint - I'll check it out :) !
Strange!!! uncaughtexception called even if i handle exception in my acitivity. Any idea.
C
Community

I posted the simple solution for custom handling of Android crashes a long ago. It's a little hacky however it works on all Android versions (including the Lollipop).

First a little bit of theory. The main issues when you use uncaught exception handler in Android come with the exceptions thrown in the main (aka UI) thread. And here is why. When the app starts system calls ActivityThread.main method which prepares and starts the Main looper of your app:

public static void main(String[] args) {
  …
  …
    Looper.prepareMainLooper();
  …
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

Main looper is responsible for processing messages posted in the UI thread (including all messages related to UI rendering and interaction). If an exception is thrown in the UI thread it will be caught by your exception handler, but since you're out of loop() method you won't be able to show any dialog or activity to the user as there's no one left to process UI messages for you.

The proposed solution is quite simple. We run Looper.loop method by our own and surround it with try-catch block. When an exception is caught we process it as we want (for example start our custom report activity) and call Looper.loop method again.

The following method demonstrates this technique (it should be called from the Application.onCreate listener):

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);
        }
    }
}

As you can see the uncaught exception handler is used only for the exceptions thrown in background threads. The following handler catches those exceptions and propagates them to the UI thread:

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);
            }
        });
    }
}

An example project which uses this technique is available on my GitHub repo: https://github.com/idolon-github/android-crash-catcher


As one might guess, this way it's not only possible to show custom error dialog, but also to allow the user to ignore the exception and continue work with the application (and while it looks like a bad idea for the published apps, it could be pretty convenient during a debug or testing session).
Hi, while this works in catching uncaught exceptions but, for some reason, this code is always throwing exceptions. Initially I though it was because of the RuntimeException line that you have in the startCatcher method but I am still getting exception after removing it. I am not sure if that is a required thing. Anyway the exception that I get is java.lang.RuntimeException: Performing pause of activity that is not resumed. I believe when I am trying to start my own looper the system pauses the activity which is about to start? I am not sure but any help would be appreciated. Thanks
also if I remove the startCatcher i.e. run the app without your code then everything works fine without any exceptions.
@sttaq What version of Android do you use?
I think I was trying this on 2.3.x
J
Jared Burrows

I think to disable that in your uncaughtException() method do not call previousHandler.uncaughtException() where previousHandler is set by

previousHandler = Thread.getDefaultUncaughtExceptionHandler();

C
Community

FWIW I know this is slightly off-topic, but we've been using Crittercism's free plan with success. They also offer some premium features, like handling the exception so the app doesn't crash.

In the free version, the user still sees the crash, but at least I get the email and the stack trace.

We also use the iOS version (but I've heard from my colleagues that it is not quite as good).

Here are similar questions:

Global uncaught exception handler -> email log to me?

Is it possible to create some sort of global exception handler in Android?


J
Jared Burrows

It doesn't work until you call

android.os.Process.killProcess(android.os.Process.myPid());

at the very end of your UncaughtExceptionHandler.