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)
原创文章 67 获赞 68 访问量 6万+

猜你喜欢

转载自blog.csdn.net/AlpinistWang/article/details/104464109