美文网首页
CrashHandler未捕获类型异常处理

CrashHandler未捕获类型异常处理

作者: 已经是咸鱼的小涛orz | 来源:发表于2017-08-07 18:11 被阅读0次

当用户在使用app出现崩溃现象时,我们需要知道是什么原因,并将原因记录下来上到服务器,这样以后我们就可以知道具体是什么原因了

  一般而言,我们在开发的时候为了避免出现bug,在一些疑似有可能出现bug的地方会主动加上try{ } catch( ) { },当然有些时候编译器的检测机制也会提示我们需要加try catch比如JSONObject取值的时候就会让做空指针异常处理。
  不过不管做多少预处理,但是!!!bug总会在你意想不到的时候突然降临-。-

没有一点点防备,也没有一丝顾虑,你就这样出现在我的世界里,带给我惊喜,情不自已
  如果是在开发阶段的话还不是一个多大的问题,插上USB调试看下log就行虽然并不一定能够稳定复现
but!!!项目上线出了bug,先不说用户体验不好,单开发者自己而言也是很悲催的一件事。单凭热心用户 乱七八糟,莫名其妙 的三言两语基本弄不明白是哪里的问题。
所以,这时候我们就需要一种方法,让我们知道用户app崩溃的原因。
这也就是这篇文章罗里吧嗦这么久要讲的 囧oz

和以前一样,先贴代码

public class CrashHandler implements UncaughtExceptionHandler {

    private static CrashHandler instance = null;
    private CrashHandlerListener crashHandlerListener = null;
    private UncaughtExceptionHandler defaultUncaughtExceptionHandler = null;

    private CrashHandler(){ }
    public static CrashHandler getInstance() {
        if (instance == null)
            instance = new CrashHandler();
        return instance;
    }

    public void init() {
        //  获取系统默认的为捕获异常处理器
        this.defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        //  设置当线程由于未捕获到异常而突然终止,并且没有为该线程定义其他处理程序时所调用的默认处理程序。
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    public void init(CrashHandlerListener listener) {
        init();
        this.crashHandlerListener = listener;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        writeExceptionToSDCard(throwable);
        uploadedExceptionToServer(throwable);
        //  如果系统存在默认的未捕获异常处理器则让系统处理,否则自己处理
        if (defaultUncaughtExceptionHandler != null) {
            defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
        } else {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.prepare();
                    if (crashHandlerListener != null) {
                        crashHandlerListener.uncaughtException();
                    } else {
                        ToastUtil.showShort("很抱歉,程序出现异常,即将退出.");
                        new Handler().postDelayed(new Runnable(){
                            public void run() {
                                App.getInstance().exit();
                            }
                        }, 2000);
                    }
                    Looper.loop();
                }
            }).start();
        }
    }

    /**
     * 将异常信息写入SD卡
     * @param throwable 未捕获异常
     */
    private void writeExceptionToSDCard(Throwable throwable) {
        // TODO: 2017/8/4 将异常信息写入SD卡
        Log.i("###########", throwable.toString());
    }

    /**
     * 将异常信息上传到服务器
     * @param throwable 未捕获异常
     */
    private void uploadedExceptionToServer(Throwable throwable) {
        // TODO: 2017/8/4 将异常信息上传到服务器
    }

    public interface CrashHandlerListener {
        void uncaughtException();
    }

}

单例

  其实没有必要使用单例模式,我这边使用单例仅是强迫症。。。因为CrashHandler是需要在整个App运行状态中去捕获全局所有异常的,因此一般都是在Application中去初始化,然后初始化之后也没有其他什么操作了,毕竟目的是捕获异常。所以总体而言,CrashHandler只在Application中被调用了一次,单例不单例也就没什么影响了。

UncaughtExceptionHandler

un(没有)caught(接住)exception(异常)handler(处理)

    @FunctionalInterface
    public interface UncaughtExceptionHandler {
        void uncaughtException(Thread var1, Throwable var2);
    }

android本身是提供有未捕获异常处理机制的,所以这就省了很多事了,我们只需要考虑拦截实现。
在刚刚的代码中,可以看到两句看起来略有冲突的语句:

this.defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);

第一句Thread.getDefaultUncaughtExceptionHandler()是获取系统默认的处理器
第二句Thread.setDefaultUncaughtExceptionHandler(this)是把我们实现的UncaughtExceptionHandler接口CrashHandler设置为系统默认的处理器
So,理一下,我们先获取了一个系统默认的处理器,然后把我们自己实现的接口设置为默认的。
首先Thread.getDefaultUncaughtExceptionHandler()维护了一个异常处理器,把这个对象赋值给defaultUncaughtExceptionHandler,这样当我们想通过系统默认处理器的时候就可以通过defaultUncaughtExceptionHandler去调用了;
然后Thread.setDefaultUncaughtExceptionHandler(this)这个方法是为了当系统检测到未捕获异常时会使用我们实现的接口
其实说起来有点啰嗦,想想a、b变量交互的逻辑应该就能清楚很多
说完这些,我们也发现了重点就是我们实现的接口uncaughtException(thread, throwable)

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        writeExceptionToSDCard(throwable);  //  写入SD卡
        uploadedExceptionToServer(throwable);  //  上传到服务器
        //  如果系统存在默认的未捕获异常处理器则让系统处理,否则自己处理
        if (defaultUncaughtExceptionHandler != null) {
            defaultUncaughtExceptionHandler.uncaughtException(thread, throwable);
        } else {
            // TODO: 2017/8/7 自己的处理
        }
    }

相关文章

  • CrashHandler未捕获类型异常处理

    当用户在使用app出现崩溃现象时,我们需要知道是什么原因,并将原因记录下来上到服务器,这样以后我们就可以知道具体是...

  • Android 优化 处理全局未捕获异常,并重启应用

    【Android 优化 处理全局未捕获异常,并重启应用】 1、创建一个CrashHandler类 2、在Appli...

  • Python异常处理

    Python异常处理 一、捕获异常 1.异常捕获语法 2.错误类型捕获 except:处理所有异常。except ...

  • 6未捕获的异常

    如果一个异常未被捕获,则由名为未捕获异常处理程序的函数截取。未捕获的异常处理程序总是导致程序退出,但可能会在这之前...

  • 综合技术

    1.全局捕获异常可以自己创建crashHandler实现Thread.UncaughtExceptionHandl...

  • 捕获异常信息CrashHandler

    注意事项: 建好的文件有时候看不到,需要重启手机或者是调用 MediaScannerConnection.scan...

  • springboot 异常捕获和处理

    springboot 异常捕获和处理 异常捕获处理

  • iOS swift try

    try 捕获异常 try 出现异常处理异常 try? 不处理异常,返回一个可选值类型,出现异常返回nil try!...

  • go基本语法操作

    异常处理 异常类型error 异常捕获recover 异常抛出panic 字符串处理 字符串常用操作 正则表达式 ...

  • WPF处理未捕获异常

    如果程序中出现未捕获的异常,程序通常会直接崩溃,也不知道哪里出了问题。在App.xaml.cs文件中加入以下代码,...

网友评论

      本文标题:CrashHandler未捕获类型异常处理

      本文链接:https://www.haomeiwen.com/subject/lusalxtx.html