APP全局异常捕获,并保存本地文件

  1 public class CrashHandler implements Thread.UncaughtExceptionHandler {
  2 
  3     public static final String TAG = "CrashHandler";
  4 
  5     // 系统默认的UncaughtException处理类
  6     private Thread.UncaughtExceptionHandler mDefaultHandler;
  7     // CrashHandler实例
  8     private static CrashHandler INSTANCE = new CrashHandler();
  9     // 程序的Context对象
 10     private Context mContext;
 11 
 12     //用来存储设备信息和异常信息
 13     private Map<String, String> infos = new HashMap<String, String>();
 14 
 15     //用于格式化日期,作为日志文件名的一部分
 16     private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
 17 
 18     /**
 19      * 保证只有一个CrashHandler实例
 20      */
 21     private CrashHandler() {
 22     }
 23 
 24     /**
 25      * 获取CrashHandler实例 ,单例模式
 26      */
 27     public static CrashHandler getInstance() {
 28         return INSTANCE;
 29     }
 30 
 31     /**
 32      * 初始化
 33      * @param context
 34      */
 35     public void init(Context context) {
 36         mContext = context;
 37         // 获取系统默认的UncaughtException处理器
 38         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
 39         // 设置该CrashHandler为程序的默认处理器
 40         Thread.setDefaultUncaughtExceptionHandler(this);
 41     }
 42 
 43     /**
 44      * 当UncaughtException发生时会转入该函数来处理
 45      */
 46     @Override
 47     public void uncaughtException(Thread thread, Throwable ex) {
 48         // ToastUtil.show(mContext, ex.getMessage());
 49         if (!handleException(ex) && mDefaultHandler != null) {
 50             // 如果用户没有处理则让系统默认的异常处理器来处理
 51             mDefaultHandler.uncaughtException(thread, ex);
 52         } else {
 53             try {
 54                 Thread.sleep(500);
 55             } catch (InterruptedException e) {
 56                 Log.e(TAG, "error : ", e);
 57             }
 58             // 退出程序
 59             android.os.Process.killProcess(android.os.Process.myPid());
 60             System.exit(1);
 61 //            KJActivityStack.create().AppExit(mContext);// 结束整个应用程序
 62         }
 63     }
 64 
 65     /**
 66      * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
 67      * @param ex
 68      * @return true:如果处理了该异常信息;否则返回false.
 69      */
 70     private boolean handleException(Throwable ex) {
 71         if (ex == null) {
 72             return false;
 73         }
 74         // 使用Toast来显示异常信息
 75         new Thread() {
 76             @Override
 77             public void run() {
 78                 Looper.prepare();
 79                 Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
 80                 Looper.loop();
 81             }
 82         }.start();
 83         //保存日志文件
 84         String path = saveCrashInfo2File(ex);
 85         return true;
 86     }
 87 
 88     /**
 89      * 保存错误信息到文件中
 90      * @param ex
 91      * @return 返回文件名称, 便于将文件传送到服务器
 92      */
 93     private String saveCrashInfo2File(Throwable ex) {
 94         infos = PhoneUtils.collectDeviceInfo(mContext);
 95         StringBuffer sb = new StringBuffer();
 96         for (Map.Entry<String, String> entry : infos.entrySet()) {
 97             String key = entry.getKey();
 98             String value = entry.getValue();
 99             sb.append(key + "=" + value + "\n");
100         }
101         Writer writer = new StringWriter();
102         PrintWriter printWriter = new PrintWriter(writer);
103         ex.printStackTrace(printWriter);
104         Throwable cause = ex.getCause();
105         while (cause != null) {
106             cause.printStackTrace(printWriter);
107             cause = cause.getCause();
108         }
109         printWriter.close();
110         String result = writer.toString();
111         sb.append(result);
112         FileOutputStream fos = null;
113         try {
114             long timestamp = System.currentTimeMillis();
115             String time = formatter.format(new Date());
116             String fileName = "crash-" + time + "-" + timestamp + ".log";
117             if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
118                 String path = "/sdcard/aaaaaaaaaaaaaaaaaaaaacrash/";
119 //                String path = mContext.getCacheDir() + "/crash/";
120                 File dir = new File(path);
121                 if (!dir.exists()) {
122                     dir.mkdirs();
123                 }
124                 fos = new FileOutputStream(path + fileName);
125                 fos.write(sb.toString().getBytes());
126             }
127             return fileName;
128         } catch (Exception e) {
129             Log.e(TAG, "an error occured while writing file...", e);
130         } finally {
131             try {
132                 if (fos != null)
133                     fos.close();
134             } catch (IOException e) {
135                 Log.e(TAG, "an error occured while fos.close...", e);
136             }
137         }
138         return null;
139     }

 

posted on 2015-10-01 18:32  大米稀饭  阅读(488)  评论(0编辑  收藏  举报