安卓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)
})
這樣應用在崩潰之前會把日誌發送到後臺,方便程序員定位解決問題。當然這裏也可以通過寫文件的處理方式先保存這些報錯信息,待日後方便再行上傳採集。