Crash抓取App全局log保存到本地 发表于 2017-08-08 | 分类于 Android | 阅读次数 代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168/** * created by JesseHev */public class CrashHandler implements Thread.UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; // 系统默认的UncaughtException处理类 private Thread.UncaughtExceptionHandler mDefaultHandler; // CrashHandler实例 private static CrashHandler INSTANCE = new CrashHandler(); public static String LOG_PATH = "/jesse/log"; private Map<String, String> mInfos = new HashMap<>(); private Context mContext; private CrashHandler() { } public static CrashHandler getInstance() { return INSTANCE; } public void init(Context context) { mContext = context; // 获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时会转入该函数来处理 */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { // 如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { try { Thread.sleep(2000); } catch (InterruptedException e) { Log.e(TAG, "error : ", e); } // 退出程序 System.exit(10); } } /** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. * * @return true:如果处理了该异常信息;否则返回false. */ private boolean handleException(Throwable ex) { if (ex == null) { return false; } new Thread() { @Override public void run() { Looper.prepare(); Looper.loop(); } }.start(); //获取设备信息 getDeviceInfo(); // 保存日志文件 saveCrashInfo(ex); return true; } /** * 保存错误信息到文件中 */ private void saveCrashInfo(Throwable ex) { StringBuilder sb = new StringBuilder(); sb.append(printDeviceInfo()); sb.append(getExceptionString(ex)); try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String path = getLogPath(); FileOutputStream fos = new FileOutputStream(path); fos.write(sb.toString().getBytes()); fos.close(); } } catch (Exception e) { } } /** * 将异常信息转换为字符串 */ public static String getExceptionString(Throwable ex) { StringBuilder err = new StringBuilder(); err.append("ExceptionDetailed:\n"); err.append("====================Exception Info====================\n"); err.append(ex.toString()); err.append("\n"); StackTraceElement[] stack = ex.getStackTrace(); for (StackTraceElement stackTraceElement : stack) { err.append(stackTraceElement.toString()).append("\n"); } Throwable cause = ex.getCause(); if (cause != null) { err.append("【Caused by】: "); err.append(cause.toString()); err.append("\n"); StackTraceElement[] stackTrace = cause.getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { err.append(stackTraceElement.toString()).append("\n"); } } return err.toString(); } /** * 获取log保存目录 */ public static String getLogPath() { DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); String time = dateFormat.format(new Date()); String path = android.os.Environment.getExternalStorageDirectory().getPath() //+ File.separator + LOG_PATH + "-" + time + ".txt"; File log = new File(path); if (!log.getParentFile().exists()) { log.getParentFile().mkdirs(); } if (!log.exists()) { try { log.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } return path; } /** * 收集设备参数信息 */ public String printDeviceInfo() { StringBuilder sb = new StringBuilder(); sb.append("====================Device Info====================\n"); for (Map.Entry<String, String> entry : mInfos.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); sb.append(key + "=" + value + "\n"); } sb.append("=================================================\n"); return sb.toString(); } /** * 通过反射获取设备信息 */ private void getDeviceInfo() { Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); mInfos.put(field.getName(), field.get(null).toString()); } catch (Exception e) { } } }}