Toast not showing up in UnCaughtExceptionHandler

2019-04-06 15:42发布

I am using this code to handle any uncaught exceptions which might cause my application to crash.

public class ExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
    private final Context myContext;

    public ExceptionHandler(Context context) {

        myContext = context;
    }

    public void uncaughtException(Thread thread, Throwable exception) {

        Toast.makeText(myContext,
                "The application has crashed, and a report is sent to the admin",
                Toast.LENGTH_SHORT).show();
        StringWriter stackTrace = new StringWriter();
        exception.printStackTrace(new PrintWriter(stackTrace));
        System.err.println(stackTrace);// You can use LogCat too
        Intent intent = new Intent(myContext, CrashActivity.class);
        myContext.startActivity(intent);
        Process.killProcess(Process.myPid());
        System.exit(10);
    }
}

When i run it with a known but uncaught exception(just to test), activity "CrashActivity" is called but the Toast which must come before it is not showing up.

Actually i wanted to show only Toast and then call myContext.finish(); instead of going to the CrashActivity. But that toast in not visible.

Where am i wrong?

3条回答
乱世女痞
2楼-- · 2019-04-06 16:08

Found this question while googling for exact the same problem. As far as I can tell it is not necessary to have the Toast.show() called from the UI thread as long as there is an Application context.

AFAIK: The problem that here occurs is the following: You're trying to show a Toast and immediately afterwards your application is shut down by the VM, which means your Toast is shutdown as well.

A solution for the problem is the following:

  • Run the Toast from a sepearate Thread
  • Delay shutdown of your application in the Uncaught Exception Handler.

What I do is the following:

In Application::onCreate():

Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread thread, Throwable ex)
    {
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(getApplicationContext(), "Application crashed", Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();

        try
        {
            Thread.sleep(4000); // Let the Toast display before app will get shutdown
        }
        catch (InterruptedException e)
        {
            // Ignored.
        }
    }
});

It is similiar to how the Toast notification in ACRA works (in fact this is where I got the hint from).

查看更多
唯我独甜
3楼-- · 2019-04-06 16:19

Calling System.exit(0) from within Android UncaughtExceptionHandler helps application recover from error and relaunch last Activity. IMHO, user experience gets improved significantly. However, this approach needs to be tried and tested on multiple android platforms. Have tried this on GB and JB. It worked fine. Additionally, I heard from others (I am new to Android) that invoking System.exit() is not recommended in Android but ..could use this as a nice recovery option for android application crashes.

    public void uncaughtException(Thread thread, Throwable ex) {
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();  
                Toast.makeText(YourActivity.this, "Application has Crashed. Recovering now.", Toast.LENGTH_LONG).show();
                /* Log relevant message/analytics from here. */
                System.exit(1);
                Looper.loop();
            }
        }.start();
    }
查看更多
ら.Afraid
4楼-- · 2019-04-06 16:23

You are probably calling the Toast from a thread while a toast should be called from the UI thread...

If this isn't helping, please provide us the logcat output so we can see what kind of error you are getting.

查看更多
登录 后发表回答