我很久以前发布了用于自定义处理Android崩溃的简单解决方案。这有点小巧,但是它可以在所有Android版本(包括Lollipop)上使用。
首先介绍一点理论。在Android中使用未捕获的异常处理程序时,主要的问题是在主线程(又名UI)中引发了异常。这就是为什么。当应用启动时,系统调用ActivityThread.main方法,该方法准备并启动应用的Main looper:
public static void main(String[] args) {
…
…
Looper.prepareMainLooper();
…
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
主循环程序负责处理在UI线程中发布的消息(包括与UI渲染和交互相关的所有消息)。如果在UI线程中引发了异常,它将被您的异常处理程序捕获,但是由于您不在loop()
方法不正确您将无法向用户显示任何对话框或活动,因为没有人可以处理UI消息为了你。
提出的解决方案非常简单。我们Looper.loop
自己运行方法,并用try-catch块将其包围。捕获到异常后,我们将根据需要对其进行处理(例如,启动自定义报告活动),然后Looper.loop
再次调用方法。
下面的方法演示了此技术(应从Application.onCreate
侦听器调用):
private void startCatcher() {
UncaughtExceptionHandler systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();
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