1. 程式人生 > >實現UncaughtExceptionHandler來實現獲取應用全域性的crash資訊

實現UncaughtExceptionHandler來實現獲取應用全域性的crash資訊

    Android應用不可避免的會出現各種崩潰crash,平時我們可能會通過try-catch來捕獲異常,可是我們總不可能每一段程式碼都try-catch,所以我們還是會有很多捕獲不到的異常,而且一旦應用釋出後,在客戶端出現的問題我們也不能debug除錯,也沒有logcat了,客戶端崩潰後用戶體驗很不好,但是我們因為捕獲不到相關異常資訊想要修復程式也顯得有心無力,其實Android是提供了一個可以設定的全域性異常捕獲方法,就是Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler)

他的英文註解是:

/**
     * Sets the default uncaught exception handler. This handler is invoked in
     * case any Thread dies due to an unhandled exception.
     *
     * @param handler
     *            The handler to set or null.
     */

大概意思就是設定預設未捕獲的異常處理handler,這個handler可以在任意執行緒被未處理的異常喚醒。也就是說只要你的程式發生了沒被處理的異常就會呼叫這個handler來處理異常,是不是感覺很厲害。

使用方法:

1.寫一個類實現UncaughtExceptionHandler介面,實現uncaughtException方法;

2.每次發生異常會自動呼叫uncaughtException方法,所以在這裡寫出你希望發生錯誤時的處理方法,例如把錯誤資訊上傳伺服器或者寫到本地磁碟檔案或者彈出dialog提示使用者等。

3.在你的程式一執行就初始化這個類,所以一般都是在application裡初始化這個類。

demo效果:


程式碼解析:

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static 
CrashHandler crashHandler = new CrashHandler(); private Context mContext; private Thread.UncaughtExceptionHandler mDefaultCaughtExceptionHandler; //使用餓漢單例模式 public static CrashHandler getInstance() { return crashHandler; } public void init(Context context) { //獲取預設的系統異常捕獲器 mDefaultCaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); //把當前的crash捕獲器設定成預設的crash捕獲器 Thread.setDefaultUncaughtExceptionHandler(this); mContext = context.getApplicationContext(); } @Override public void uncaughtException(Thread thread, Throwable ex) { //注意需要清空所有已經啟動的activity,否則你的錯誤提示框可能會彈出很多次 MyApplication.clearActivity(); //啟動錯誤處理頁面,你也可以在這裡寫上傳伺服器什麼的 Intent intent = new Intent("com.crash.start"); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra("message",ex.getMessage()); mContext.startActivity(intent); Process.killProcess(Process.myPid());//殺掉程序 /*我看網上不少栗子是下面這麼寫的,但是實際測試的結果是,Android6.0以上的系統這麼寫沒有任何問題, 但如果是6.0以下的系統主執行緒異常這樣寫也沒有問題, * 但如果6.0以下系統並且異常出現在子執行緒中,這麼寫就會執行系統那個醜陋的白色程式異常停止執行的提示框, * 然後點選確定後直接退出程式,不會執行你希望的友好退出介面*/ // if (mDefaultCaughtExceptionHandler != null) { // mDefaultCaughtExceptionHandler.uncaughtException(thread,ex); // } else { // Process.killProcess(Process.myPid());//殺掉程序 // } } }

在你的application裡初始化這個類:

public class MyApplication extends Application {

    private static ArrayList<Activity> activities;
@Override
public void onCreate() {
        super.onCreate();
activities = new ArrayList<>();
CrashHandler.getInstance().init(this);//初始化全域性異常捕獲器
}

    /**新增activity*/
public static void addActivity(Activity activity) {
        activities.add(activity);
}

    /**結束所有被新增的activity*/
public static void clearActivity() {
        for (Activity activity : activities) {
            activity.finish();
}
    }
}
別忘了去AndroidManifest裡宣告application
<application
android:name=".MyApplication"