Android-构建全局的异常捕捉类
整体思路
构建Android应用全局的异常信息捕捉类,当App Crash的时候,能够获取崩溃信息,包括ExceptionMessage,手机信息,版本信息等。然后写入文件存到手机sd卡中。当应用下次开启的时候读取文件上传服务器,为后期的热修复做准备。
- 首先新建一个ExceptionCrashHandler类实现Thread.UncaughtExceptionHandler接口,并重写uncaughtException(Thread t, Throwable e)方法,这个方法当有异常发生的时候会被回调。
- ExceptionCrashHandler整个应用有一份即可,所以可以使用单例模式要构建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| private static ExceptionCrashHandler mInstance; private Context mContext; private Thread.UncaughtExceptionHandler mDefaultExceptionHandler;
public static ExceptionCrashHandler getInstance() { if (mInstance == null) { synchronized (ExceptionCrashHandler.class) { if (mInstance == null) { mInstance = new ExceptionCrashHandler(); } } } return mInstance; }
public void init(Context context) { mContext = context; Thread.currentThread().setUncaughtExceptionHandler(this); mDefaultExceptionHandler = Thread.currentThread().getDefaultUncaughtExceptionHandler(); }
|
1
| ExceptionCrashHandler.getInstance().init(this);
|
- 在uncaughtException方法中去做一些信息的收集工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @Override public void uncaughtException(Thread t, Throwable e) { Logger.e("报异常了!");
String crashFileName = saveInfo2SD(e);
Logger.d("CrashFileName--->" + crashFileName);
cacheCrashLog(crashFileName);
mDefaultExceptionHandler.uncaughtException(t, e); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
private String saveInfo2SD(Throwable e) { String fileName = null; StringBuffer stringBuffer = new StringBuffer(); Map<String, String> simpleInfo = getSimpleInfo(mContext); for (Map.Entry<String, String> entry : simpleInfo.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); stringBuffer.append(key).append("=").append(value).append("\n"); }
stringBuffer.append(getExceptionInfo(e));
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { File dir = new File(mContext.getFilesDir() + File.separator + "crash" + File.separator);
if (dir.exists()) { deleteDir(dir); }
if (!dir.exists()) { dir.mkdirs(); }
try { fileName = dir.toString() + File.separator + getAssignTime("yyyy_MM_dd_HH_mm") + ".txt"; FileOutputStream fos = new FileOutputStream(fileName); fos.write(stringBuffer.toString().getBytes()); fos.flush(); fos.close();
} catch (Exception ex) { ex.printStackTrace(); } } return fileName; }
|
- 获取手机信息可以通过反射,获取Build类中的字段信息。这里面可以拿到手机型号,版本信息。可能某些bug是在特定机型上才出现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
private String getMobileInfo() { StringBuffer stringBuffer = new StringBuffer(); Field[] fields = Build.class.getDeclaredFields(); try { for (Field field : fields) { field.setAccessible(true); String name = field.getName(); String value = field.get(null).toString();
stringBuffer.append(name + "=" + value); stringBuffer.append("\n"); } } catch (IllegalAccessException e) { e.printStackTrace(); } return stringBuffer.toString(); }
|
- 还要对外提供一个获取异常信息文件的方法,用于再次启动应用的时候获取该文件并上传
1 2 3 4 5 6 7 8 9 10
|
public File getCrashFile() { SharedPreferences sharedPreferences = mContext.getSharedPreferences("crash", Context.MODE_PRIVATE); String carshFileName = sharedPreferences.getString("CRASH_FILE_NAME", ""); return new File(carshFileName); }
|
- 在MainActivity启动的时候,拿到该文件直接上传服务器,我们这里没有服务器,就直接把信息打印出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| if (crashFile.exists()){ Logger.d("上传到服务器"); try { FileReader fileReader = new FileReader(crashFile); int len = 0;
char[] buf = new char[1024]; while ((len = fileReader.read(buf)) != -1){ String crashInfo = new String(buf, 0, len); Logger.d(crashInfo); }
} catch (Exception e) { e.printStackTrace(); } }
|
- 写完之后可以在应用的任何地方写一个异常试一试,第一次点击挂掉,然后再点一次就可以拿到崩溃信息了。
源码:
https://github.com/Sun0630/EssayJoke/blob/master/baselibrary/src/main/java/com/sx/baselibrary/ExceptionCrashHandler.java
总结: 这样当应用崩溃的时候开发人员就可以及时的获取崩溃信息,针对性的修复bug,做热修复等等。当然bug监控也有很好的第三方平台,友盟和腾讯的Bugly都不错。可以自己选择。