I'm developing an app, and every once in a while one of my background worker threads will have an uncaught exception of one sort or another. These exceptions crash that thread, but since it's not on the UI thread the App keeps running. How can I force these uncaught exceptions in the background threads to crash the whole app? It would be nice if the same contextual crash information (such as the stack trace) were available.
I want to do this so that when I release the app to my testers it doesn't become unresponsive. Instead, when the background thread has an uncaught exception the App will go to it's crash handler and send me a report (I'm using ACRA, but that shouldn't matter). That's better than an app that silently fails.
Late answer, but I was asking myself the same question.
We use Crashlytics in Production, but if the app is build for development, some assertion are enabled, and logging an error actually throws it, so that we developer can detect any incorrect behavior.
But as you remarked, throwing an error in a background thread doesn't crash the app.
To ensure the app crashes immediately when build for development we simply use an Handler on the main looper to throw the exception on the main thread.
It looks a bit like this :
public static void assertTrue(boolean condition, String msg) {
if (condition) {
return;
}
final IllegalStateException e = new IllegalStateException(message);
if (BuildConfig.RELEASE) {
Crashlytics.logException(e);
return;
}
Log.e("ASSERT", message, e);
if (Looper.getMainLooper() != Looper.myLooper()) {
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
throw e;
}
});
}
throw e;
}
Original version below
Actually, after further testing I have found that you can simplify your code by just handing the exception to your main thread directly.
public static <T extends Exception> void throwOnMainThread(T exception) {
Thread mainThread = Looper.getMainLooper().getThread();
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, exception);
}
This will crash the main thread from anywhere and is safe to call even without setting a custom UncaughtExceptionHandler.
Original answer:
Consider the following static method for crashing the main thread from a background thread:
public static <T extends Exception> void throwOnMainThread(final T exception) {
Handler mainThreadHandler = new Handler(Looper.getMainLooper());
mainThreadHandler.post(new Runnable() {
@Override
public void run() {
Thread currentThread = Thread.currentThread();
currentThread.getUncaughtExceptionHandler().uncaughtException(currentThread, exception);
}
});
}
First we get a Handler for the Main Thread via the main Looper. Then we post a Runnable which will invoke the UncaughtExceptionHandler of that thread and hand it our exception.
Put this into a utils class and you will be able to throw exceptions on the main thread from basically anywhere.
Crashing the main thread could then be achieved by using
ThreadUtils.throwOnMainThread(new RuntimeException());
for example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With