Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 374
Samuh Avatar asked May 04 '10 10:05

Samuh


People also ask

What are the different ways to create a global exception handler?

Adding a Global Exception HandlerIn the Design tab part of the Ribbon, select New > Global Handler. The New Global Handler window opens. Type in a Name for the handler and save it in the project path. Click Create, a Global Exception Handler is added to the automation project.

What is uncaught exception handler?

You can use UncaughtExceptionHandler to handle the exception those causes a thread to terminate abruptly. Java doc for UncaughtExceptionHandler - Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception.

What is uncaught exception explain with example?

When an uncaught exception occurs, the JVM calls a special private method known dispatchUncaughtException( ), on the Thread class in which the exception occurs and terminates the thread. The Division by zero exception is one of the example for uncaught exceptions.

What is global exception handler in Java?

One of the core features that makes it robust is the exception handling framework. It means the program can gracefully exit at the times of error, instead of just crashing. Whenever an exception occurs, an Exception object is constructed, either by the JVM or by the method executing the code.


2 Answers

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.

like image 105
fadden Avatar answered Sep 19 '22 18:09

fadden


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

like image 22
Idolon Avatar answered Sep 19 '22 18:09

Idolon