關於crash捕獲的那些事
Android應用不可避免地會發生crash,也稱之爲奔潰,其可能由於Android系統底層的bug,也可能是由於不充分的機型適配或者是糟糕的網絡狀況。當crash發生時,系統會kill掉正在執行的程序,現象就是閃退或者提示用戶程序已停止執行。
Android爲了能夠獲取應用的crash信息,提供了一個解決方案。在Thread中有一個方法setDefaultUncaughtExceptionHandler,如下所示。
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
// Android-removed: SecurityManager stubbed out on Android
/*
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
*/
defaultUncaughtExceptionHandler = eh;
}
該方法設置系統的默認異常處理器,當crash發生的時候,系統就會回調UncaughtExceptionHandler的uncaughtException方法。這也就意味着,我們可以在uncaughtException方法中獲取crash異常信息,可以選擇把異常信息存儲到SD卡中,然後再合適的時機通過網絡將crash信息上傳到服務器上(於是我們就可以爲所欲爲了,hhhh)。
一個典型的異常處理器的實現步驟爲:
① 實現一個UncaughtExceptionHandler對象,在它的uncaughtException方法中獲取異常信息並將其存儲在SD卡中或者上傳到服務器供開發人員分析。
② 調用Thread的setDefaultUncaughtExceptionHandler方法將它設置爲線程默認的異常處理器。由於默認異常處理器是Thread類的靜態成員,因此它作用對象是當前進程的所有線程。
一個典型的異常處理器實現如下所示(筆者簡略了處理異常信息代碼)。
public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static CrashHandler sInstance;
private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
private Context mContext;
private CrashHandler() {
}
public static CrashHandler getInstance() {
if (sInstance == null) {
synchronized (CrashHandler.class) {
if (sInstance == null) {
sInstance = new CrashHandler();
}
}
}
return sInstance;
}
public void init(Context context) {
mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
mContext = context.getApplicationContext();
}
/**
* 獲取異常信息並處理
* @param t
* @param e
*/
@Override
public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
// ...
}
}
有了CrashHandler之後,只需要在Application初始化的時候爲線程設置CrashHandler即可,如下所示。
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
}
}
這樣只需要對uncaughtException方法進行實現就可以實現目標了。需要注意的是,代碼中被catch的異常不會交給CrashHandler處理,CrashHandler只能接收那些未被捕獲的異常。
參考資料:《Android開發藝術探索》