zoukankan      html  css  js  c++  java
  • android 程序漰溃 后台handle处理类

    [代码] [Java]代码

    001 import java.io.File;
    002 import java.io.FileOutputStream;
    003 import java.io.FilenameFilter;
    004 import java.io.PrintWriter;
    005 import java.io.StringWriter;
    006 import java.io.Writer;
    007 import java.lang.Thread.UncaughtExceptionHandler;
    008 import java.lang.reflect.Field;
    009 import java.util.Arrays;
    010 import java.util.Properties;
    011 import java.util.TreeSet;
    012
    013 import android.content.Context;
    014 import android.content.pm.PackageInfo;
    015 import android.content.pm.PackageManager;
    016 import android.content.pm.PackageManager.NameNotFoundException;
    017 import android.os.Build;
    018 import android.os.Looper;
    019 import android.util.Log;
    020 import android.widget.Toast;
    021
    022 /**
    023 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类 来接管程序,并记录 发送错误报告.. 註冊方式
    024 * CrashHandler crashHandler = CrashHandler.getInstance(); //注册crashHandler
    025 * crashHandler.init(getApplicationContext()); //发送以前没发送的报告(可选)
    026 * crashHandler.sendPreviousReportsToServer();
    027 *
    028 */
    029 public class CrashHandler implements UncaughtExceptionHandler {
    030 /** Debug Log tag */
    031 public static final String TAG = "CrashHandler";
    032 /**
    033 * 是否开启日志输出,在Debug状态下开启, 在Release状态下关闭以提示程序性能
    034 * */
    035 public static final boolean DEBUG = true;
    036 /** 系统默认的UncaughtException处理类 */
    037 private Thread.UncaughtExceptionHandler mDefaultHandler;
    038 /** CrashHandler实例 */
    039 private static CrashHandler INSTANCE;
    040 /** 程序的Context对象 */
    041 private Context mContext;
    042
    043 /** 使用Properties来保存设备的信息和错误堆栈信息 */
    044 private Properties mDeviceCrashInfo = new Properties();
    045 private static final String VERSION_NAME = "versionName";
    046 private static final String VERSION_CODE = "versionCode";
    047 private static final String STACK_TRACE = "STACK_TRACE";
    048 /** 错误报告文件的扩展名 */
    049 private static final String CRASH_REPORTER_EXTENSION = ".cr";
    050
    051 /** 保证只有一个CrashHandler实例 */
    052 private CrashHandler() {
    053 }
    054
    055 /** 获取CrashHandler实例 ,单例模式 */
    056 public static CrashHandler getInstance() {
    057 if (INSTANCE == null) {
    058 INSTANCE = new CrashHandler();
    059 }
    060 return INSTANCE;
    061 }
    062
    063 /**
    064 * 初始化,注册Context对象, 获取系统默认的UncaughtException处理器, 设置该CrashHandler为程序的默认处理器
    065 *
    066 * @param ctx
    067 */
    068 public void init(Context ctx) {
    069 mContext = ctx;
    070 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    071 Thread.setDefaultUncaughtExceptionHandler(this);
    072 }
    073
    074 /**
    075 * 当UncaughtException发生时会转入该函数来处理
    076 */
    077 @Override
    078 public void uncaughtException(Thread thread, Throwable ex) {
    079 if (!handleException(ex) && mDefaultHandler != null) {
    080 // 如果用户没有处理则让系统默认的异常处理器来处理
    081 mDefaultHandler.uncaughtException(thread, ex);
    082 } else {
    083 // Sleep一会后结束程序
    084 try {
    085 Thread.sleep(3000);
    086 } catch (InterruptedException e) {
    087 Log.e(TAG, "Error : ", e);
    088 }
    089 android.os.Process.killProcess(android.os.Process.myPid());
    090 System.exit(10);
    091 }
    092 }
    093
    094 /**
    095 * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. 开发者可以根据自己的情况来自定义异常处理逻辑
    096 *
    097 * @param ex
    098 * @return true:如果处理了该异常信息;否则返回false
    099 */
    100 private boolean handleException(Throwable ex) {
    101 if (ex == null) {
    102 return true;
    103 }
    104 final String msg = ex.getLocalizedMessage();
    105 // 使用Toast来显示异常信息
    106 new Thread() {
    107 @Override
    108 public void run() {
    109 Looper.prepare();
    110 Toast.makeText(mContext, "程序出错啦:" + msg, Toast.LENGTH_LONG)
    111 .show();
    112 Looper.loop();
    113 }
    114
    115 }.start();
    116 // 收集设备信息
    117 collectCrashDeviceInfo(mContext);
    118 // 保存错误报告文件
    119 String crashFileName = saveCrashInfoToFile(ex);
    120 // 发送错误报告到服务器
    121 sendCrashReportsToServer(mContext);
    122 return true;
    123 }
    124
    125 /**
    126 * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告
    127 */
    128 public void sendPreviousReportsToServer() {
    129 sendCrashReportsToServer(mContext);
    130 }
    131
    132 /**
    133 * 把错误报告发送给服务器,包含新产生的和以前没发送的.
    134 *
    135 * @param ctx
    136 */
    137 private void sendCrashReportsToServer(Context ctx) {
    138 String[] crFiles = getCrashReportFiles(ctx);
    139 if (crFiles != null && crFiles.length > 0) {
    140 TreeSet<String> sortedFiles = new TreeSet<String>();
    141 sortedFiles.addAll(Arrays.asList(crFiles));
    142
    143 for (String fileName : sortedFiles) {
    144 File cr = new File(ctx.getFilesDir(), fileName);
    145 postReport(cr);
    146 cr.delete();// 删除已发送的报告
    147 }
    148 }
    149 }
    150
    151 private void postReport(File file) {
    152 // TODO 使用HTTP Post 发送错误报告到服务器
    153 // 这里不再详述,开发者可以根据OPhoneSDN上的其他网络操作
    154 // 教程来提交错误报告
    155 }
    156
    157 /**
    158 * 获取错误报告文件名
    159 *
    160 * @param ctx
    161 * @return
    162 */
    163 private String[] getCrashReportFiles(Context ctx) {
    164 File filesDir = ctx.getFilesDir();
    165 FilenameFilter filter = new FilenameFilter() {
    166 public boolean accept(File dir, String name) {
    167 return name.endsWith(CRASH_REPORTER_EXTENSION);
    168 }
    169 };
    170 return filesDir.list(filter);
    171 }
    172
    173 /**
    174 * 保存错误信息到文件中
    175 *
    176 * @param ex
    177 * @return
    178 */
    179 private String saveCrashInfoToFile(Throwable ex) {
    180 Writer info = new StringWriter();
    181 PrintWriter printWriter = new PrintWriter(info);
    182 ex.printStackTrace(printWriter);
    183
    184 Throwable cause = ex.getCause();
    185 while (cause != null) {
    186 cause.printStackTrace(printWriter);
    187 cause = cause.getCause();
    188 }
    189
    190 String result = info.toString();
    191 printWriter.close();
    192 mDeviceCrashInfo.put(STACK_TRACE, result);
    193 String fileName = "";
    194 try {
    195 long timestamp = System.currentTimeMillis();
    196 fileName = "crash-" + timestamp + CRASH_REPORTER_EXTENSION;
    197 FileOutputStream trace = mContext.openFileOutput(fileName,
    198 Context.MODE_PRIVATE);
    199 mDeviceCrashInfo.store(trace, "");
    200 trace.flush();
    201 trace.close();
    202 return fileName;
    203 } catch (Exception e) {
    204 Log.e(TAG, "an error occured while writing report file..."
    205 + fileName, e);
    206 }
    207 return null;
    208 }
    209
    210 /**
    211 * 收集程序崩溃的设备信息
    212 *
    213 * @param ctx
    214 */
    215 public void collectCrashDeviceInfo(Context ctx) {
    216 try {
    217 PackageManager pm = ctx.getPackageManager();
    218 PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
    219 PackageManager.GET_ACTIVITIES);
    220 if (pi != null) {
    221 mDeviceCrashInfo.put(VERSION_NAME,
    222 pi.versionName == null ? "not set" : pi.versionName);
    223 mDeviceCrashInfo.put(VERSION_CODE, pi.versionCode);
    224 }
    225 } catch (NameNotFoundException e) {
    226 Log.e(TAG, "Error while collect package info", e);
    227 }
    228 // 使用反射来收集设备信息.在Build类中包含各种设备信息,
    229 // 例如: 系统版本号,设备生产商 等帮助调试程序的有用信息
    230 // 具体信息请参考后面的截图
    231 Field[] fields = Build.class.getDeclaredFields();
    232 for (Field field : fields) {
    233 try {
    234 field.setAccessible(true);
    235 mDeviceCrashInfo.put(field.getName(), field.get(null));
    236 if (DEBUG) {
    237 Log.d(TAG, field.getName() + " : " + field.get(null));
    238 }
    239 } catch (Exception e) {
    240 Log.e(TAG, "Error while collect crash info", e);
    241 }
    242
    243 }
    244
    245 }
    246
    247 }
  • 相关阅读:
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    linux中的cd ..和cd -命令有什么区别?
    GCC使用
  • 原文地址:https://www.cnblogs.com/tuncaysanli/p/2469042.html
Copyright © 2011-2022 走看看