前言:
每当我们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(" sdkVersion:" + deviceInfo.sdkVersion); stringBuffer.append(" manufacturer:" + deviceInfo.manufacturer); stringBuffer.append(" model:" + deviceInfo.model); stringBuffer.append(" version" + ConfigManager.getVersionName(context)); stringBuffer.append(" errorStr:" + result); stringBuffer.append(" time:" + 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); } }
展望:我们也可以把日志再下次启动的时候发送至我们自己的日志服务器,监控用户错误信息