Android中设置全局未捕获的异常处理程序的理想方法
我想为我的Android应用程序中的所有线程设置全局未捕获的异常处理程序。 所以,在我的Application
子类中,我将Thread.UncaughtExceptionHandler
的实现设置为未捕获异常的默认处理程序。
Thread.setDefaultUncaughtExceptionHandler(
new DefaultExceptionHandler(this));
在我的实现中,我试图显示一个AlertDialog
显示适当的异常消息。
但是,这似乎并不奏效。 每当任何未处理的线程抛出异常时,我都会获得库存,操作系统默认对话框(“对不起! - 应用程序已停止 - 意外对话”)。
什么是为未捕获的异常设置默认处理程序的正确和理想的方式?
这应该是你需要做的一切。 (确保你之后导致进程停止 - 事情可能处于不确定状态。)
首先要检查的是Android处理程序是否仍在调用。 有可能你的版本被调用但失败致命,并且system_server在看到进程崩溃时显示一个通用对话框。
在处理程序顶部添加一些日志消息,以查看它是否到达那里。 从getDefaultUncaughtExceptionHandler打印结果,然后抛出未捕获的异常以导致崩溃。 密切关注logcat输出,看看发生了什么。
很久以前,我发布了自定义处理Android崩溃的简单解决方案。 这是一个小黑客,但它适用于所有Android版本(包括棒棒糖)。
首先是一点理论。 在Android中使用未捕获的异常处理程序时遇到的主要问题与主要(又名UI)线程中引发的异常有关。 这是为什么。 当应用程序启动系统调用ActivityThread.main方法准备并启动应用程序的主循环器时:
public static void main(String[] args) {
…
…
Looper.prepareMainLooper();
…
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
主要looper负责处理UI线程中发布的消息(包括与UI呈现和交互相关的所有消息)。 如果在UI线程中抛出异常,它将被异常处理程序捕获,但由于您不在loop()
方法中,因此无法向用户显示任何对话框或活动,因为没有人留下来为您处理UI消息。
提出的解决方案非常简单。 我们自己运行Looper.loop
方法,并使用try-catch块来包围它。 当发现异常时,我们按照我们的要求处理它(例如,开始我们的自定义报告活动)并再次调用Looper.loop
方法。
以下方法演示了这种技术(它应该从Application.onCreate
侦听器中调用):
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);
}
}
}
正如你所看到的,未捕获的异常处理程序仅用于在后台线程中抛出的异常。 以下处理程序捕获这些异常并将它们传播到UI线程:
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);
}
});
}
}
使用这种技术的示例项目可在我的GitHub仓库中找到:https://github.com/idolon-github/android-crash-catcher
FWIW我知道这有点偏离主题,但我们一直在使用Crittercism的成功免费计划。 它们还提供一些高级功能,例如处理异常,以便应用程序不会崩溃。
在免费版本中,用户仍然看到崩溃,但至少我得到了电子邮件和堆栈跟踪。
我们也使用iOS版本(但我从同事那里听说它不太好)。
这里有类似的问题:
上一篇: Ideal way to set global uncaught exception Handler in Android