android程序crash时的异常上报

无论程序写的多完美, 发生crash都是无法避免的, 可能是机型适配, 也可能是你的代码写的不当。 当crash发生时, 系统会kill掉你的程序, 表现为闪退或者程序已停止运行, 这对用户来说是很不友好的, 当crash发生时,我们应该处理两件事,一是弹出一个通知友好的告知用户我们的程序出了问题要关闭,这样比闪退要温和一些,二是我们应该收集crash信息,在合适的时机上报后台服务器,在后续版本中修复这个bug。
要完成这个工作,核心是对java的Thread类有一定深度的理解。
在Thread.java源码中, 有一个静态变量defaultUncaughtHandler,被程序中所有的Thread共享。在程序中可调用Thread.setDefaultUncaughtExceptionHandler()来设置这个全局变量,从字面上理解就是设置系统默认的异常处理器。

    /**
     * Holds the default handler for uncaught exceptions, in case there is one.
     */
    private static UncaughtExceptionHandler defaultUncaughtHandler;

    /**
     * Sets the default uncaught exception handler. This handler is invoked in
     * case any Thread dies due to an unhandled exception.
     *
     * @param handler
     *            The handler to set or null.
     */
    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
        Thread.defaultUncaughtHandler = handler;
    }

实现步骤:

1. 实现自己的异常处理Handler

public class BrowserCrashHandler implements UncaughtExceptionHandler {
    private static BrowserCrashHandler mInstance = null;
    public static BrowserCrashHandler getInstance() {
        if (null == mInstance) {
            mInstance = new BrowserCrashHandler();
        }
        return mInstance;
    }
    public void init(Context ctx) {
    //将当前实例设置为系统默认的异常处理器,这个异常处理器被所有的Thread共享.
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext = ctx;
    }
//核心, 重写uncaughtException()方法,当程序有未被捕获的异常,系统会自动调用uncaughtException()方法。
//thread为未捕获异常发生所在的线程, ex为未捕获的异常实例。
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
    //这里可以保存当前程序的状态,比如已经打开了哪些页面
        //弹出通知告知用户程序即将关闭
        //根据ex, 保存crash信息到sdcard
    android.os.Process.killProcess(android.os.Process.myPid());
    System.exit(0);
    }
}

2. 初始化自定义的异常处理器

在Application的onCreate对它进行初始化, 因为在app的生命周期中,它是第一个被启动的, 早于任何的Activity, Service等.

public class BrowserApplicationContext extends Application {
    @Override
    public void onCreate() {
    BrowserCrashHandler.getInstance().init(this);
    }

效果:

模拟一个空指针异常
TextView tv = null;
tv.setVisibility(View.VISIBLE);
在自定义BrowserCrashHandler的uncaughtException()处打个断点, call stack如下.

crashHandler_1.png
crashHandler_2.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容