一、CrashHandler
自定义 Crash 处理器:
object CrashHandler : Thread.UncaughtExceptionHandler {
private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
fun init() {
Thread.setDefaultUncaughtExceptionHandler(this)
}
override fun uncaughtException(thread: Thread, throwable: Throwable) {
Log.d("~~~", "$thread, $throwable")
defaultHandler?.uncaughtException(thread, throwable)
}
}
二、初始化
Application 中初始化此 CrashHandler:
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
CrashHandler.init()
}
}
我们在 CrashManager 中调用 Thread.setDefaultUncaughtExceptionHandler
函数将默认的未捕获异常处理器设置为 CrashHandler 类,当存在未捕获异常时,系统会回调 uncaughtException
方法,我们可以在此方法中将崩溃信息打印出来,或保存到 sd 卡中。
为了不影响系统原有的处理未捕获异常的逻辑,我们在 init
方法中先将默认的崩溃处理器保存下来,存储在 defaultHandler 中,在 uncaughtException
方法中让默认的 handler 也处理此异常。
三、测试
在 MainActivity 中测试一下,本例中布局文件只有一个 id 为 btn 的按钮,故不再给出布局文件:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn.setOnClickListener {
throw NullPointerException("test")
}
}
}
点击按钮,Logcat 会打印出以下日志:
~~~: Thread[main,5,main], java.lang.NullPointerException: test
四、打印 stackTrace
修改 CrashHandler,将崩溃的 stackTrace 打印出来:
object CrashHandler : Thread.UncaughtExceptionHandler {
private val defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
fun init() {
Thread.setDefaultUncaughtExceptionHandler(this)
}
override fun uncaughtException(thread: Thread, throwable: Throwable) {
Log.d("~~~", StringBuilder("$thread, $throwable, stackTrace: ").apply {
throwable.stackTrace.forEach {
appendln(it.toString())
}
}.toString())
defaultHandler?.uncaughtException(thread, throwable)
}
}
修改后,再运行上述测试,Logcat 输出:
~~~: Thread[main,5,main], java.lang.NullPointerException: test, stackTrace: com.example.crashmanager.MainActivity$onCreate$1.onClick(MainActivity.kt:14)
android.view.View.performClick(View.java:7251)
android.view.View.performClickInternal(View.java:7228)
android.view.View.access$3500(View.java:802)
android.view.View$PerformClick.run(View.java:27843)
android.os.Handler.handleCallback(Handler.java:883)
android.os.Handler.dispatchMessage(Handler.java:100)
android.os.Looper.loop(Looper.java:214)
android.app.ActivityThread.main(ActivityThread.java:7116)
java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925)