安卓app运行过程中会产生一些异常(Exception),当这些异常能够被捕获的时候,程序本身就可以通过try/catch来处理异常,但是当这些异常不能被捕获(UncaughtException)的时候,就交给系统的默认的未捕获异常处理程序来处理,而默认的处理方式就是退出应用并打印出异常信息。对应用崩溃信息的采集,就是要在系统接手处理UncaughtException之前,先将报错信息写文件或发后台,再交给系统处理(退出应用),故:
1、保存系统UncaughtException处理对象Handler
2、自己写一个UncaughtExceptionHandler,把它设置给系统,等到出现异常的时候先自己处理,再用1中保存的默认UncaughtException处理对象Handler来收尾(退出应用)
val defaultHandler: Thread.UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler { thread, throwable ->
if (throwable == null) {
defaultHandler.uncaughtException(thread, throwable)
return@UncaughtExceptionHandler
}
val writer: Writer = StringWriter()
val printWriter = PrintWriter(writer)
throwable.printStackTrace(printWriter)
var cause = throwable.cause
while (cause != null) {
cause.printStackTrace(printWriter)
cause = cause.cause
}
printWriter.flush()
printWriter.close()
val result = writer.toString()
val addCrashBuilder = AddCrash.newBuilder()
addCrashBuilder.message = result
addCrashBuilder.androidVersion = Build.VERSION.RELEASE
addCrashBuilder.phoneModel = Build.MODEL
addCrashBuilder.romBrand = Build.BRAND
addCrashBuilder.romVersion = Build.DISPLAY
val addCrash=addCrashBuilder.build()
HttpManager.getInstance().doPost(addCrash.javaClass.simpleName,addCrash.toByteArray(),null)
Thread(Runnable {
Looper.prepare()
Toast.makeText(
context, "正在上传崩溃日志...", Toast.LENGTH_LONG
).show()
Looper.loop()
}).start()
try {
Thread.sleep(2000)
} catch (e: InterruptedException) {
e.printStackTrace()
}
defaultHandler.uncaughtException(thread, throwable)
})
这样应用在崩溃之前会把日志发送到后台,方便程序员定位解决问题。当然这里也可以通过写文件的处理方式先保存这些报错信息,待日后方便再行上传采集。