一、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)