在Android中设置全局未捕获的exception处理程序的理想方法

我想为我的Android应用程序中的所有线程设置全局未捕获的exception处理程序。 所以,在我的Application子类中,我将Thread.UncaughtExceptionHandler的实现设置为未捕获exception的默认处理程序。

 Thread.setDefaultUncaughtExceptionHandler( new DefaultExceptionHandler(this)); 

在我的实现中,我试图显示一个AlertDialog显示适当的exception消息。

但是,这似乎并不奏效。 无论何时,任何未处理的线程都会抛出exception,我得到股票,操作系统默认对话框(“Sorry!-Application-has-stopped-unexpectedly dialog”)。

什么是正确和理想的方式来设置未捕获的exception的默认处理程序?

这应该是你需要做的一切。 (确保你之后会导致进程停顿 – 事情可能处于一个不确定的状态。)

首先要检查的是Android处理程序是否仍然被调用。 可能是你的版本被调用,但是失败致命,system_server在看到进程崩溃时显示一个通用对话框。

在处理程序的顶部添加一些日志消息,看看它是否到达那里。 从getDefaultUncaughtExceptionHandler打印结果,然后抛出未捕获的exception以导致崩溃。 关注logcat输出,看看发生了什么事情。

我发布了自定义处理Android崩溃的简单解决scheme很久以前。 这是一个小黑客,但它适用于所有的Android版本(包括棒棒糖)。

首先是一点理论。 在Android中使用未捕获的exception处理程序时遇到的主要问题是在主(又名UI)线程中抛出的exception。 这是为什么。 当应用程序启动系统调用ActivityThread.main方法准备并启动您的应用程序的主循环 :

 public static void main(String[] args) { … … Looper.prepareMainLooper(); … Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } 

主要looper负责处理UI线程中发布的消息(包括所有与UI呈现和交互相关的消息)。 如果在UI线程中引发exception,它将被exception处理程序捕获,但由于您不在loop()方法中,因此无法向用户显示任何对话框或活动,因为没有人留给为您处理UI消息。

build议的解决scheme非常简单。 我们自己运行Looper.loop方法,并用try-catch块来包围它。 当一个exception被捕获时,我们按照我们的要求处理它(例如,开始我们的自定义报告活动)并再次调用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); } } } 

正如您所看到的,未捕获的exception处理程序仅用于在后台线程中抛出的exception。 以下处理程序捕获这些exception并将其传播到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仓库中find: https : //github.com/idolon-github/android-crash-catcher

FWIW我知道这有点偏离主题,但我们一直在使用Crittercism的成功免费计划 。 他们还提供一些高级function,如处理exception,以便应用程序不会崩溃。

在免费版本,用户仍然看到崩溃,但至less我得到的电子邮件和堆栈跟踪。

我们也使用iOS版本(但是我从同事那里听说,它不太好)。


这里有类似的问题:

  • 全局未捕获exception处理程序 – >电子邮件日志给我?
  • 是否有可能在Android中创build某种全局exception处理程序?

我想在你的uncaughtException()方法中禁用这个,不要调用previousHandler.uncaughtException(),其中previousHandler是由

 previousHandler = Thread.getDefaultUncaughtExceptionHandler(); 

在你打电话之前它不工作

 android.os.Process.killProcess(android.os.Process.myPid()); 

在你的UncaughtExceptionHandler的最后。