前言:
每當我們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); } }
展望:我們也可以把日誌再下次啟動的時候傳送至我們自己的日誌伺服器,監控使用者錯誤資訊