android自定义异常日志收集器
来源:互联网 发布:可爱p图软件 编辑:程序博客网 时间:2024/05/16 14:05
android自定义异常日志收集器
为什么要掌握自定义异常日志收集器:
android开发中,经常会app闪退,报异常,通常是通过编辑器捕获异常日志,
分析异常日志定位问提,并解决。
如果测试人员或者用户安装app后,出现闪退,需要捕获异常日志,提供给程序员,
分析解决问题。
需要实现的效果:
app安装到手机上后,在使用App的过程中出现了异常报错,
将会把报错的异常日志记录到手机的本地存储中。
实现思路:
1.用自定义的异常处理器替换安卓系统自带的异常处理器
2.重写异常处理方法 uncaughtException ,
使用Toast友好提示用户程序异常。
重新逻辑为捕获异常信息,并写入手机的本地文件。
留出写入到服务器的扩展口。
实现代码:
应用层调用:
// 异常处理,不需要处理时注释掉这两句即可! CrashHandler crashHandler = CrashHandler.getInstance(); // 注册crashHandler crashHandler.init(getApplicationContext());
自定义的异常日志收集器:
CrashHandler.java:
public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; // 系统默认的UncaughtException处理类 private UncaughtExceptionHandler mDefaultHandler; // CrashHandler实例 private static CrashHandler INSTANCE = new CrashHandler(); // 程序的Context对象 private Context mContext; // 用来存储设备信息和异常信息private Map<String, Object> infos = new HashMap<String, Object>(); // 用于格式化日期,作为日志文件名的一部分 @SuppressLint("SimpleDateFormat")private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); /** 保证只有一个CrashHandler实例 */ private CrashHandler() { } /** 获取CrashHandler实例 ,单例模式 */ public static CrashHandler getInstance() { if (INSTANCE == null) { INSTANCE = new CrashHandler(); } return INSTANCE; } /** * 初始化,注册Context对象, * 获取系统默认的UncaughtException处理器, * 设置该CrashHandler为程序的默认处理器 * * @param context */ public void init(Context context) { mContext = context; // 获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时会转入该函数来处理 */ @Override public void uncaughtException(Thread thread, Throwable ex) {// ScreenManager.getScreenManager().popActivity(Pay.activity);// arg0.stop();// arg0.destroy(); if (!handleException(ex) && mDefaultHandler != null) { // 如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { try { Thread.sleep(2000); } catch (InterruptedException e) { Log.e(TAG, "error : ", e); }// MyApplication.getApplication().exit(true); System.exit(10); } } /** * 自定义错误处理,收集错误信息 * 发送错误报告等操作均在此完成. * 开发者可以根据自己的情况来自定义异常处理逻辑 * @param ex * @return true:如果处理了该异常信息; 否则返回false */ private boolean handleException(Throwable ex) { if (ex == null) { return false; }// final String msg = ex.getLocalizedMessage();// if (msg == null) {// return false;// } final Throwable exfinal=ex; // 使用Toast来显示异常信息 new Thread() { @Override public void run() { Looper.prepare(); Toast.makeText(mContext, "很抱歉,程序累了,休息一下马上回来...", Toast.LENGTH_SHORT).show();// Toast.makeText(mContext, exfinal.toString(),// Toast.LENGTH_LONG).show(); // MsgPrompt.showMsg(mContext, "程序出错啦", msg+"\n点确认退出"); Looper.loop(); } }.start(); // 收集设备参数信息 //collectDeviceInfo(mContext); // 保存日志文件 saveCrashInfo2File(ex); // 发送错误报告到服务器 //sendCrashReportsToServer(mContext); return true; } /** * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告 */ public void sendPreviousReportsToServer() { sendCrashReportsToServer(mContext); } /** * 把错误报告发送给服务器,包含新产生的和以前没发送的. * * @param context */ private void sendCrashReportsToServer(Context context) { String[] crFiles = getCrashReportFiles(context); if (crFiles != null && crFiles.length > 0) { TreeSet<String> sortedFiles = new TreeSet<String>(); sortedFiles.addAll(Arrays.asList(crFiles)); for (String fileName : sortedFiles) { File carshReport = new File(context.getFilesDir(), fileName); postReport(carshReport); carshReport.delete();// 删除已发送的报告 } } } private void postReport(File file) { // TODO 发送错误报告到服务器 } /** * 获取错误报告文件名 * * @param context * @return */ private String[] getCrashReportFiles(Context context) { File filesDir = context.getFilesDir(); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".txt"); } }; return filesDir.list(filter); } public void collectDeviceInfo(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES); if (pi != null) { String versionName = pi.versionName == null ? "null" : pi.versionName; String versionCode = pi.versionCode + ""; infos.put("versionName", versionName); infos.put("versionCode", versionCode); } } catch (NameNotFoundException e) { Log.e(TAG, "an error occured when collect package info", e); } Field[] fields = Build.class.getDeclaredFields(); for (Field field : fields) { try { field.setAccessible(true); infos.put(field.getName(), field.get(null).toString()); Log.d(TAG, field.getName() + " : " + field.get(null)); } catch (Exception e) { Log.e(TAG, "an error occured when collect crash info", e); } } } /** * 保存错误信息到文件中 * @param ex * @return */ private String saveCrashInfo2File(Throwable ex) { StringBuffer sb = new StringBuffer(); // for (Map.Entry entry : infos.entrySet()) { // String key = entry.getKey(); // String value = entry.getValue(); // sb.append(key + "=" + value + "\n"); // } 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(); sb.append(result); infos.put("EXEPTION", ex.getLocalizedMessage()); infos.put("STACK_TRACE", result); try { // Time t = new Time("GMT+8"); // t.setToNow(); // 取得系统时间 // int date = t.year * 10000 + t.month * 100 + t.monthDay; // int time = t.hour * 10000 + t.minute * 100 + t.second; long timestamp = System.currentTimeMillis(); String time = formatter.format(new Date()); String fileName = "crash-" + time + "-" + timestamp + ".txt"; if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { String path = Environment.getExternalStorageDirectory().getPath()+"/我的安卓/crash/"; File dir = new File(path); if (!dir.exists()) { dir.mkdirs(); } FileOutputStream fos = new FileOutputStream(path + fileName); fos.write(sb.toString().getBytes()); fos.close(); // FileOutputStream trace = mContext.openFileOutput(fileName, // Context.MODE_PRIVATE); // mDeviceCrashInfo.store(trace, ""); // trace.flush(); // trace.close(); } return fileName; } catch (Exception e) { Log.e(TAG, "an error occured while writing file...", e); } return null; }}
当安装在手机的app出现闪退时,就会在本地存储的内部存储中我的安卓文件夹里写人txt的日志文件
阅读全文
0 0
- android自定义异常日志收集器
- Android自定义错误日志收集
- Android log日志异常捕获信息收集类
- Android项目的错误异常收集日志记录
- android应用开发中收集的异常日志解决方法记录
- Android崩溃日志收集
- Android日志收集
- Android崩溃日志收集
- Android 日志收集
- Android Crash日志收集
- Android Crash日志收集
- Android 日志错误收集
- Android错误异常收集
- Android错误异常收集
- android 异常收集
- Android一点 异常收集
- android 异常收集
- Android异常收集
- 关于稳定性测试
- 文字间距、首行缩进
- Linux安装配置Git
- Oracle之数据泵
- netcdf流场展示
- android自定义异常日志收集器
- openvswitch使用手册
- python分布式rpc框架zerorpc安装及使用教程
- 斐波那契数列及系列问题
- 集合操作
- JQuery(1)
- Spring AOP 四大通知
- 第一个HTML程序
- ImageView中XML属性src和background的区别