我正在开发一个应用程序,每隔一段时间,我的一个后台工作线程就会有一个未捕获的异常。这些异常使该线程崩溃,但由于它不在 UI 线程上,因此应用程序继续运行。如何在后台线程中强制这些未捕获的异常使整个应用程序崩溃?如果相同的上下文崩溃信息(例如堆栈跟踪)可用,那就太好了。
我想这样做,以便当我将应用程序发布给我的测试人员时,它不会变得无响应。相反,当后台线程有未捕获的异常时,应用程序将转到它的崩溃处理程序并向我发送报告(我正在使用 ACRA,但这不重要)。这比静默失败的应用程序要好。
迟到的答案,但我问自己同样的问题。
我们在生产环境中使用 Crashlytics,但如果应用程序是为开发而构建的,则会启用一些断言,并且记录错误实际上会抛出它,以便我们的开发人员可以检测到任何不正确的行为。
但正如您所说,在后台线程中抛出错误不会导致应用程序崩溃。
为了确保应用程序在构建开发时立即崩溃,我们只需在主循环器上使用一个处理程序来在主线程上抛出异常。
它看起来有点像这样:
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;
}
以下为原版
实际上,经过进一步测试,我发现您可以通过直接将异常交给主线程来简化代码。
public static <T extends Exception> void throwOnMainThread(T exception) {
Thread mainThread = Looper.getMainLooper().getThread();
mainThread.getUncaughtExceptionHandler().uncaughtException(mainThread, exception);
}
这将使主线程从任何地方崩溃,即使没有设置自定义 UncaughtExceptionHandler 也可以安全调用。
原答案:
考虑以下从后台线程中使主线程崩溃的静态方法:
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);
}
});
}
首先,我们通过主 Looper 获得主线程的处理程序。然后我们发布一个 Runnable,它将调用该线程的 UncaughtExceptionHandler 并将我们的异常交给它。
将其放入 utils 类中,您将能够从基本上任何地方在主线程上抛出异常。
然后可以通过使用来实现使主线程崩溃
ThreadUtils.throwOnMainThread(new RuntimeException());
例如。
您可以在实现的类中捕获未捕获的异常java.lang.Thread.UncaughtExceptionHandler
。
uncaughtException
函数中。Thread.setDefaultUncaughtExceptionHandler()
;并给出您的异常处理程序类的实例。