Question

I have a Handler(Thread) on which I post Runnables. In case a Runnable by mistake throws a RuntimeException, the whole app process crashes. As a default that sounds sensible, but I would like to catch such runtime exceptions, log an error, and continue running. I have difficulty making that work, though. I thought of the following options:

  1. Subclass Looper and override loop() which contains the code that calls the run() method of the posted Runnables. That did not work since Looper is final.
  2. Subclass HandlerThread and override the run method which calls the Looper.loop(). In case of a runtime exception, call super.run() again and so forth. That did not work since "only one Looper may be created per thread".
  3. In each runnable class, include a try-catch for Runtime exceptions. This will work, but is rather annoying since I have rather many different Runnable classes. Also, would not protect the handler thread if a runnable by mistake forgets to include the try-catch.

In a perfect world, Looper would have a member method called registerExceptionHandler(ExceptionHandler) and the ExceptionHandler would then be called in case of an exception.

Anyone got a better suggestion?

Was it helpful?

Solution

try this custom Handler:

class H extends Handler {
    public H(Looper looper) {
        super(looper);
    }

    @Override
    public void dispatchMessage(Message msg) {
        // catch any Exception
        try {
            super.dispatchMessage(msg);
        } catch (Exception e) {
            Log.d(TAG, "dispatchMessage " + e.getMessage());
        }
    }
}

testing code:

HandlerThread ht = new HandlerThread("hthread");
ht.start();
Handler h = new H(ht.getLooper());

Runnable r = new Runnable() {
    @Override
    public void run() {
        throw new RuntimeException("testing exception");
    }
};
h.post(r);
h.post(r);

OTHER TIPS

In a perfect world DefaultExceptionHandler works like a charm for me throughout application. Where it causes unhandled Exception it triggers up.

Library named Android-Remote-StackTrace. You just need to register the broadcast of these DefaultHandlerException class in your Application class.

Snippet:

 public class Portfolio extends Application {
 static Portfolio portfolio;
 public void onCreate() {
    super.onCreate();
    portfolio = this;
    ExceptionHandler.register(portfolio);// registering for unhandled Exceptions
   }
 }

You can do various task with these such as uploading the log stack trace to your server or send mails on the crash of application as a Crash Report with your unhandled Stack Trace.

Easiest way seems to be to derive from Runnable:

public abstract class RunnableBase implements Runnable
{
    public final void run()
    {
        try {
            runInternal();
        }
        catch(Exception e) {
            // handle the exception
        }
    }

    // to be implemented by concrete subclasses
    protected abstract void runInternal();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top