场景说明
相信大家目前已上线的项目都有着捕获崩溃的机制,有些可能是自己写的,有些可能是使用第三方的,例如 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
进行异常处理的框架,我们都可以这样做。
猜你喜欢
创作不易,你的点赞是我最大的支持。
这是我的公众号,关注获取第一信息!!欢迎关注支持下,谢谢!