Android效能優化之UncaughtExceptionHandler定製自己的錯誤日誌系統

總李寫程式碼發表於2016-05-07

前言:

每當我們app測試的時候,測試人員總是對我們說這裡崩潰了,那裡掛掉了!我們只能默默接受,然後嘗試著重現bug,更可悲的是有時候bug很難復現,為了解決這種現狀所以我們要嘗試這建立一個自己的bug日誌系統。

實現原理:

Java為我們提供了一個機制,用來捕獲並處理在一個執行緒物件中丟擲的未檢測異常,以避免程式終止。我們可以通過UncaughtExceptionHandler來實現這種機制。

 

具體實現:

public class CrashManager implements UncaughtExceptionHandler {
    public static final String TAG = "CrashHandler";
    // CrashHandler例項
    private static CrashManager instance;
    // 程式的Context物件
    private Application application;
    // 系統預設的UncaughtException處理類
    private UncaughtExceptionHandler mDefaultHandler;

    /**
     * 保證只有一個CrashHandler例項
     */
    private CrashManager(Context context) {
        application = (Application) context.getApplicationContext();
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 獲取CrashHandler例項 ,單例模式
     */
    public static CrashManager getInstance(Context context) {
        CrashManager inst = instance;
        if (inst == null) {
            synchronized (CrashManager.class) {
                inst = instance;
                if (inst == null) {
                    inst = new CrashManager(context.getApplicationContext());
                    instance = inst;
                }
            }
        }
        return inst;
    }

    /**
     * 當UncaughtException發生時會轉入該函式來處理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        TaskManager.getInstance(application).saveErrorLog(ex);
        mDefaultHandler.uncaughtException(thread, ex);
    }

}

日誌寫入sdcard程式碼:

public class SaveErrorTask<T> extends Task<Object, Object, Void> {
    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA);
    private Context context;
    private Throwable ex;

    public SaveErrorTask(Context context, Throwable ex) {
        setPriority(TaskPriority.UI_LOW);
        this.context = context;
        this.ex = ex;
    }

    @Override
    protected Void doInBackground(Object... arg0) {
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        String time = formatter.format(new Date());
        String fileName = time + ".txt";
        StringBuilder stringBuffer = new StringBuilder();
        DeviceInfo deviceInfo = Utils.getDeviceInfo(context);
        stringBuffer.append("\nsdkVersion:" + deviceInfo.sdkVersion);
        stringBuffer.append("\nmanufacturer:" + deviceInfo.manufacturer);
        stringBuffer.append("\nmodel:" + deviceInfo.model);
        stringBuffer.append("\nversion" + ConfigManager.getVersionName(context));
        stringBuffer.append("\nerrorStr:" + result);
        stringBuffer.append("\ntime:" + time);
        String filePath = CacheFileUtils.getLogPath(fileName);
        CacheFileUtils.saveErrorStr(filePath, stringBuffer.toString());
        return null;
    }
}

初始化:

public class MyApplication extends MultiDexApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        //初始化 錯誤日子系統
        CrashManager.getInstance(this);
       
    }
}

 

 

展望:我們也可以把日誌再下次啟動的時候傳送至我們自己的日誌伺服器,監控使用者錯誤資訊

相關文章