Android 記錄未捕獲異常

一、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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章