Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toast not showing up in UnCaughtExceptionHandler

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?

like image 241
Archie.bpgc Avatar asked Jul 23 '12 09:07

Archie.bpgc


1 Answers

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).

like image 103
Briareos386 Avatar answered Sep 30 '22 21:09

Briareos386