阅读 123

给Bugly增加自定义处理异常功能 | 创作者训练营第二期

场景说明

相信大家目前已上线的项目都有着捕获崩溃的机制,有些可能是自己写的,有些可能是使用第三方的,例如 Bugly。

但是,无论使用什么框架,基本上都是围绕着UncaughtExceptionHandler进行,也就是说,只有应用崩溃了才能上报异常信息。

嗯?为什么是应用崩溃了才能上报信息?

那是因为大部分框架都是使用这种方式进行异常捕获和上报:

        Thread.setDefaultUncaughtExceptionHandler(object : Thread.UncaughtExceptionHandler {
            override fun uncaughtException(t: Thread, e: Throwable) {
                //捕获异常,进行记录,上报。
                ...
                //调用系统默认的崩溃处理。
                ...
            }
        })
复制代码

defaultUncaughtExceptionHandler只能存在一个,它并不是责任链形式。假如你再重新设置一个的话,之前的那个就会失效,所以,这就导致了假如使用了第三方框架,那么一切异常处理都完全交给它了,很难做到去修改它里面的逻辑,除非它提供了源码或者提供相应的回调。

所以,我在想,有没有什么方式既能使用到它的异常捕获机制,但是最终的异常信息由我们自己处理,而不是简简单单的调用系统默认的崩溃处理,例如,我们想新增自动重启功能。

大家可以跟随我一起探索!

请系好安全带,GO!GO!GO!

不入虎穴焉得虎子。首先,我们得先了解下UncaughtExceptionHandler的基本使用。

UncaughtExceptionHandler使用说明

大致思路如下:

  • 存储系统默认异常处理
  • 实现UncaughtExceptionHandler接口
  • uncaughtException进行异常处理逻辑,然后调用系统默认异常处理
  • 调用Thread.setDefaultUncaughtExceptionHandler()进行设置

具体代码如下:

MyUncaughtExceptionHandler.kt

object MyUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
    //获取系统默认的异常处理机制
    private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler =
        Thread.getDefaultUncaughtExceptionHandler()
    override fun uncaughtException(t: Thread, e: Throwable) {
        //自己处理
        Log.e("uncaughtException TAG", e.message.toString())
//        //交给系统默认处理
//        defaultUncaughtExceptionHandler.uncaughtException(t, e)
    }
}
复制代码

BaseApplication.kt

class BaseApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler)
    }
}
复制代码

由此,我们就能捕获到 App 的崩溃异常了。

现在,我们就可以考虑另外一个问题了。

我们知道 Bugly 里面也有相关的这些代码,我们怎么样才能做得到把系统默认崩溃处理拿到手进行修改?

em...

拦截Bugly的崩溃处理

首先,我们得想下,Bugly 是如何拿到系统默认defaultUncaughtExceptionHandler的?

毫无疑问,就是通过Thread.getDefaultUncaughtExceptionHandler()这个方法进行获取,并且存储起来,就像我们下面所写的代码一样。

private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler =
        Thread.getDefaultUncaughtExceptionHandler()
复制代码

既然如此,那么,我们在 Bugly 初始化代码之前就拿到系统默认的defaultUncaughtExceptionHandler存储起来,然后再把自定义的MyUncaughtExceptionHandler设置为默认,那么,Bugly 拿到的defaultUncaughtExceptionHandler不就是我们自定义的那个吗?

然后,Bugly 处理完异常后,调用系统默认崩溃处理,其实就是调用到我们的崩溃处理,这时,我们想干啥都行了!

代码如下:

class BaseApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler)
        CrashReport.initCrashReport(getApplicationContext(), "123456", false)
    }
}
复制代码

MyUncaughtExceptionHandler的代码我重新贴下:

object MyUncaughtExceptionHandler : Thread.UncaughtExceptionHandler {
    //获取系统默认的异常处理机制
    private var defaultUncaughtExceptionHandler: Thread.UncaughtExceptionHandler =
        Thread.getDefaultUncaughtExceptionHandler()
    override fun uncaughtException(t: Thread, e: Throwable) {
        //自己处理
        Log.e("uncaughtException TAG", e.message.toString())
//        //交给系统默认处理
//        defaultUncaughtExceptionHandler.uncaughtException(t, e)
    }
}
复制代码

手写个异常,点击 View 抛出异常:

        tv_login.setOnClickListener {
            "a".toInt()
        }
复制代码

运行:

成功捕获了异常:

E/uncaughtException TAG: For input string: "a"
复制代码

Bugly 也有上报异常:

由此,我们就可以在MyUncaughtExceptionHandler中添加自己的异常处理功能了,例如重启App,或者自己收集数据什么的。

当然,这种逻辑不仅限于 Bugly,只要是围绕UncaughtExceptionHandler进行异常处理的框架,我们都可以这样做。

猜你喜欢

创作不易,你的点赞是我最大的支持。

文章分类
Android
文章标签