4

CustomExceptionHandler

public class CustomExceptionHandler implements UncaughtExceptionHandler {

private Context ctx;
private ContentResolver cr;

public CustomExceptionHandler(Context ctx, ContentResolver cr) {
    this.ctx = ctx;
    this.cr = cr;
}

public void uncaughtException(Thread t, Throwable e) {

    final Writer result = new StringWriter();
    final PrintWriter printWriter = new PrintWriter(result);
    e.printStackTrace(printWriter);
    String stacktrace = result.toString();
    printWriter.close();


    String deviceUuid = Utilities.DeviceUuid(ctx, cr);
    String bluetoothName = Utilities.LocalBluetoothName();

    AsyncTasks.ErrorLogTask logTask = new AsyncTasks.ErrorLogTask(e, bluetoothName, deviceUuid, stacktrace);
    logTask.execute();
}




}

Called from my main activity:

Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(getBaseContext(), getContentResolver()));

When an exception occurs now, i dont get the regular "unfortunately, has stopped" popup. Its just a black screen. If i remove my call from my main activity, in other words dont use the CustomExceptionHandler anymore, i get the default behaviour.

Is there any way to implement the default error behaviour in my class?

Thanks in advance!

Johan
  • 35,120
  • 54
  • 178
  • 293
  • I had the same problem, recently solved. Here is my [original post](https://stackoverflow.com/questions/46070393/replacing-default-uncaught-exception-handler-to-avoid-crash-dialog) – Alex.F Sep 06 '17 at 08:49

1 Answers1

3

You can add the following at the end of your exception handler to get the "unfortunately has stopped" dialog:

System.exit(1);

However, this will cause the process to terminate which means that your AsyncTask will not run to completion.

In any case, I would doubt that your code will run reliably anyway if you are in an uncaughtExceptionHandler, because you have no idea what the state of your application is. It might work, and it might not. What you could also try is to create a new Thread in your uncaughtExceptionHandler and have that thread sleep for a little while and then terminate the application using System.exit(). That may give your AsyncTask enough time to run to completion.

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Thanks, but im not a fan of guessing when things are complete. I've read that somethis like this might help? `previousHandler = Thread.getDefaultUncaughtExceptionHandler();` – Johan Jul 01 '12 at 11:02
  • Sure, you could save a reference to the previous handler before you set your uncaughtExceptionHandler. And then, at the end of your code in `uncaughtException` you could call `previousHandler.uncaughtException(t, e);` (assuming it is non-null). However, the effect is the same. Your process will be immediately terminated which will not give your AsyncTask a chance to run. If this is the behaviour that you want, you can just remove your uncaughtException handler entirely and just use the default behaviour. – David Wasser Jul 01 '12 at 11:08
  • Ok, because its working now with your snippet. And my asynctask still posts data to my service. How is that possible? – Johan Jul 01 '12 at 11:11
  • It is all a matter of timing. I didn't mean to say it won't work. It may work, and it may not work. It all depends on how long the VM takes to shut down and how long your AsyncTask takes to execute. It looks like you're lucky ;-) If my answer was helpful, just accept it and we can both go away happy. – David Wasser Jul 01 '12 at 11:15
  • I dont end up in the `onPostExecute` though. But what do you think of doing network related stuff in the `CustomExceptionHandler` class? Synchronous, that is. Bad idea? I will accept it as soon as i can. – Johan Jul 01 '12 at 11:15
  • Doing network-related stuff in the `CustomExceptionHandler` is a bad idea. If it takes a long time your process will get killed with an ANR. You should start another Thread to do this, but you also want to terminate the application after the network I/O is complete so that the user gets the 'application stopped working' dialog. What you could try is to move the `System.exit()` call into your AsyncTask and call it after the AsyncTask has completed its job. – David Wasser Jul 01 '12 at 11:19
  • Thanks, but it seems like the app crashes before it reaches the `onPostExecute` – Johan Jul 01 '12 at 11:24
  • What about calling `previousHandler.uncaughtException(t, e);` from the task? – Johan Jul 01 '12 at 11:27
  • Sure, you can do that. You just need to make sure that you call it from the main thread (ie: you cannot call it from inside `doInBackground()`). Otherwise it won't kill your process and give the "app stopped working" dialog. – David Wasser Jul 01 '12 at 11:50
  • I don't know what you are using this for, but if you know where your app is throwing the uncaughtException, you should add code to report this error there and not rely on using uncaughtException handler. UncaughtException handler is there as a last resort and as I said earlier you cannot rely on the state of your application. It may be totally messed up and a lot of stuff may or may not work. – David Wasser Jul 01 '12 at 11:57
  • The thing is that i dont know whats causing the error and the user is somewhere very far away from me. – Johan Jul 01 '12 at 12:03
  • I don't know what sort of application you have, but what I usually do in this case is simply write some information about the crash to a file in the file system in the uncaughtException handler and then let the app crash using `System.exit(1)`. Next time the app is started I check for the existence of this file. If it exists, I upload it to my server. If you do it this way, you aren't trying to upload the crash information when your application is in an indeterminate (and probably broken) state. You can also inform the user of what you are doing (which you may or may not want to do). – David Wasser Jul 01 '12 at 12:09
  • @DavidWasser I tried calling `System.exit(1)` (or any non-zero value) but I don't get the "has stopped" message. What I did: 1. Implement Thread.UncaughtExceptionHandler 2. Do a simple try-finally in uncaughtException and return 'System.exit(1)' Any idea? – Kapé Sep 11 '14 at 22:05
  • @DavidWasser Solved it already by looking at the [ACRA](https://github.com/ACRA/acra/blob/2d2833284c3466097aa7efcf4e575bae7ca2326d/src/main/java/org/acra/ErrorReporter.java "ACRA ErrorReporter.java") source code. Need to keep a reference to the original `UncaughtExceptionHandler` and call it again in the finally statement instead of calling `System.exit(1)`. – Kapé Sep 11 '14 at 22:26