閱讀本文大概需要8分鐘
作者: wangsj1992 出處:https://www.jianshu.com/p/8676f7a05920
前言
安卓開發中,你是否遇到過如下困擾:
場景一
開發好一個功能後送出給測試小姑娘,測試中說“app停止運作”,然後你拿着他的測試機連到自己電腦上,重複操作一下,看看log找崩潰的原因。
如果是必現的bug還好,遇到偶現的bug的蛋疼了。
場景二
可能你的項目中接入了
UncaughtExceptionHandler
,崩潰日志會以檔案的方式儲存在sd卡,但是有的裝置不支援直接檢視這些檔案,此時還得連上電腦找到這個檔案。
場景三
可能你的項目中使用了三方統計,可以統計出app崩潰的日志,但是三方統計的資料一般不是及時的,可能要等一段時間資料才能同步。
推薦一個小工具
扯了這麼多,就是少一個崩潰日志記錄檢視工具,那麼接下來推薦一個安卓開發必備的工具。
CrashCanary
是一個無侵入的安卓崩潰日志記錄庫,對你的代碼沒有任務侵入性,無需申請權限,隻需要添加依賴,即可在程式崩潰時記錄崩潰日志并可檢視所有日志。
效果如下:

快速接入
是的,這樣就接入了,你不需要添加任何代碼,真正的無侵入。
不瞞你說,這裡就是參考了
LeakCanary2
。
和
LeakCanary2
一樣,程式安裝後會多出來一個圖示為
CrashCanary
的入口,名字和你的應用名相同(感覺同名不同圖示更加人性化,因為如果你幾個app都接入了
LeakCanary
時,應用清單就會有好幾個名為Leaks的app入口,此時你可能就不知道哪個是哪個了)。
一旦你的app崩潰了,可以從這個同名的入口進入檢視日志,或者通知欄的通知進入。如下:
enterance.png
log_list.png
點選日志item進入日志詳情,詳情中記錄了崩潰的詳細日志,同時還記錄了裝置的版本、型号、cpu以及軟體版本等資訊。
detail.png
原理及涉及知識點
1,UncaughtExceptionHandler
UncaughtExceptionHandler
可以幫我們捕獲我們代碼中未捕獲而導緻崩潰的異常,源碼如下:
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
*
Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
它隻是一個接口,系統的
LoggingHandler
就是它的實作類。
2,自定義UncaughtExceptionHandler
Thread
類提供了設定
UncaughtExceptionHandler
的方法
/**
是以我們隻需要實作
UncaughtExceptionHandler
,并調用目前線程的
setDefaultUncaughtExceptionHandler
方法即可。
主要代碼如下:
public class CrashHandler implements UncaughtExceptionHandler {
主要邏輯為:首先擷取線程預設的
UncaughtExceptionHandler
,當發生異常時在
uncaughtException()
方法中首先執行自己的處理異常的邏輯,如果自己未能處理,則調用系統預設的來處理,最後退出程式。
3,記錄日志
1,首先擷取日志詳情
日志存在于
Throwable
中,從其中擷取詳情需要使用
Writer
及
PrintWriter
來擷取。
Writer writer = new StringWriter();
2,其次,要擷取系統資訊及apk資訊。
// 擷取app版本資訊
String versionCode = pi.versionCode + "";
// 擷取裝置型号等資訊
3,儲存資料
可以使用SQLite資料庫來儲存資料,這樣既不需要申請讀sd卡權限,又可以友善程式讀取。
4,日志讀取
日志是在一個和app同名的入口中檢視的,那麼如何生成這個入口呢?
首先要明确這不是另一個app,他們是一個app,不信你解除安裝這個同名app試試,你的app也會被解除安裝掉。
它其實就是一個配置了
Launcher
的
Activity
,如下:
需要注意的是該activity需要配置一個
taskAffinity
,不然這個activity會和你的應用在同一個棧中,影響正常的傳回棧邏輯。
5,無侵入
如何做到無侵入呢?和
LeakCanary2
一樣,使用
ContentProvider
,在其
onCreate()
方法中初始化我們的
CrashHandler
即可。
總結
目前業界已經存在不少更好的功能更全的工具。本文詳細講解了無侵入式的android崩潰日志記錄流程,對新手提供一些思路,希望大佬們不要噴,根據自己的需要找到一款适合自己的工具才是最重要的。
國民程式員