8

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?

Archie.bpgc
  • 23,812
  • 38
  • 150
  • 226
  • 2
    I'm not an android programmer but from the reading I have done, doesn't Toast have to be called on the UI thread? In which case, are you invoking it on the UI thread? Im guessing youve probably thought of this already though. – Jon Taylor Jul 23 '12 at 09:24
  • yeah you are right..i am not calling the toast on ui thread :( – Archie.bpgc Jul 23 '12 at 09:32

3 Answers3

10

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

Briareos386
  • 1,927
  • 18
  • 34
  • This was just what I needed since I wanted a quick (temporary) way to see some details of the exception. I found I also had to put in a `System.exit()` call after the `catch` block. Is this missing in the above? – darrenp Mar 06 '13 at 17:22
  • Pjuh. Good question. I don't exit with `System.exit()` but use the default exception handler with `_androidDefaultUncaughtExHandler.uncaughtException(thread, ex);` and setting it with `_androidDefaultUncaughtExHandler = Thread.getDefaultUncaughtExceptionHandler();` – Briareos386 Mar 21 '13 at 10:12
  • 1
    Makes sense. The default exception handler must be tidying up and calling `System.exit()`. – darrenp Mar 25 '13 at 16:32
  • @GeneSys are you sure it works? i've tried using the looper way, and for some reason it has the same exception as when i don't run on the ui thread... – android developer Jul 07 '13 at 10:36
  • Just tried exactly this code snippet on Android 4.1.1 - works perfectly as expected (Toast is displayed, app won't get shut down (freezes as no system.exit or default android exception handler is called) - @androiddeveloper would you mind opening a new question and referencing it here? – Briareos386 Jul 08 '13 at 08:08
  • i think i know why it happens. i've called System.exit because i really wanted to close the app when it crashes, so i couldn't see the toast. i though i had the exception again and again because of this problem: http://stackoverflow.com/questions/17512340/sending-crash-report-via-email-using-defaultexceptionhandler . it caused the app to restart itself after sending the crash report via gmail. the problem is caused when the crash is caused in the onCreate() method of the activity. no idea why. – android developer Jul 08 '13 at 08:14
  • The accepted answer didn't solve my problem. I think the key was to use Looper. Thanks! – ka3ak May 25 '18 at 06:53
4

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();
    }
Mohsen Afshin
  • 13,273
  • 10
  • 65
  • 90
  • how can i avoid the restarting of the app when i call System.exit() ? i want the app to really close itself when there is a crash, yet i want to capture the event and send the data via email... – android developer Jul 07 '13 at 12:43
  • `System.exit()` will in most cases close the app abruptly, which is generally not what you want. The app will crash whether you call `exit()` or not, so there is no actual need to call it explicitly. – milosmns Oct 18 '17 at 12:01
3

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.

Ferdau
  • 1,524
  • 1
  • 12
  • 21
  • Yeah i am wrong in using the Toast in a different thread. Actually i saw this in an application where when the app crashes it shows a Toast on the same activity. Is it that it actually recalls the same Activity and then shows the toast?? – Archie.bpgc Jul 23 '12 at 09:31