http://blog.csdn.net/jason0539/article/details/45602655

应用发生crash之后要查看log,判断问题出在什么地方,可是一旦应用发布出去,就要想办法把用户的崩溃日志拿到分析。

所以要在发生crash之后抓取log,然后上传到服务器,方便开发者查看,现在都有很多第三方做这方面的服务,这里说下如何自己来实现。

其实原理很简单,应用出现异常后,会由默认的异常处理器来处理异常,

我们要做的就是把这个任务接管过来,自己处理异常,包括收集日志,保存到本地,然后上传到服务器。

下面是自己实现的异常处理类。

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

使用方式如下:

在Application的onCreate中加上下面

  1. CrashHandler crashHandler = CrashHandler.getInstance();
  2. crashHandler.init(this);

这样一来,应用发生crash,自动保存log到本地了。

其实这样还有一个好处,就是不用在logcat里面翻来翻去找日志,直接到本地文件夹打开看就是了。

android开发之应用Crash自动抓取Log_自动保存崩溃日志到本地的更多相关文章

  1. APP自动化框架LazyAndroid使用手册(2)--元素自动抓取

    作者:黄书力 概述 前面的一篇博文简要介绍了安卓自动化测试框架LazyAndroid的组成结构和基本功能,本文将详细描述此框架中元素自动抓取工具lazy-uiautomaterviewer的使用方法. ...

  2. SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享

    SQL Server定时自动抓取耗时SQL并归档数据发邮件脚本分享 第一步建库和建表 USE [master] GO CREATE DATABASE [MonitorElapsedHighSQL] G ...

  3. IIS崩溃时自动抓取Dump

    背景:在客户现场,IIS有时会崩溃,开发环境没法重现这个bug,唯有抓取IIS的崩溃是的Dump文件分析. IIS崩溃时自动抓取Dump,需要满足下面几个条件 1.启动 Windows Error R ...

  4. 学习笔记CB010:递归神经网络、LSTM、自动抓取字幕

    递归神经网络可存储记忆神经网络,LSTM是其中一种,在NLP领域应用效果不错. 递归神经网络(RNN),时间递归神经网络(recurrent neural network),结构递归神经网络(recu ...

  5. 巧用Grafana和Arthas自动抓取K8S中异常Java进程的线程堆栈

    前言 近期发现业务高峰期时刻会出现CPU繁忙导致的timeout异常,通过监控来看是因为Node上面的一些Pod突发抢占了大量CPU导致的. 问: 没有限制CPU吗?是不是限制的CPU使用值就可以解决 ...

  6. 自动抓取java堆栈

    参数1 进程名字,参数2 最大线程数 例: pid为8888,达到1000个线程时自动抓取堆栈信息 ./autojstack.sh 8888 1000 & #!/bin/bashfileNam ...

  7. SQL Server定时自动抓取耗时SQL并归档数据脚本分享

    原文:SQL Server定时自动抓取耗时SQL并归档数据脚本分享 SQL Server定时自动抓取耗时SQL并归档数据脚本分享 第一步建库 USE [master] GO CREATE DATABA ...

  8. 【VIP视频网站项目】VIP视频网站项目v1.0.3版本发布啦(程序一键安装+电影后台自动抓取+代码结构调整)

    在线体验地址:http://vip.52tech.tech/ GIthub源码:https://github.com/xiugangzhang/vip.github.io 项目预览 主页面 登录页面 ...

  9. scrapy自动抓取蛋壳公寓最新房源信息并存入sql数据库

    利用scrapy抓取蛋壳公寓上的房源信息,以北京市为例,目标url:https://www.dankegongyu.com/room/bj 思路分析 每次更新最新消息,都是在第一页上显示,因此考虑隔一 ...

随机推荐

  1. 使用Spring MVC 的表单控制器SimpleFormController

    以注册过程为例,我们可能会选择继承AbstractController来实现表单的显示,继承AbstractCommandController来实现表单的处理 ,这样是可行的,但必须要维护两个控制器 ...

  2. Using the Task Parallel Library (TPL) for Events

    Using the Task Parallel Library (TPL) for Events The parallel tasks library was introduced with the ...

  3. ZOJ 3790 Consecutive Blocks

    大致题意就是给你一个数列,让你最多移除K个数字,使得连续的相同数字的长度最大,并求出最大长度. 我们将此序列按颜色排序,颜色相同的话按位置排序,那么排完序之后颜色相同的blocks就在一起,只是他们的 ...

  4. 【原】Spark中Client源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Client源码分析(一)http://www.cnblogs.com/yourarebest/p/5313006.html DriverClient中的 ...

  5. Java笔记(七)……函数

    函数的定义 定义在类中具有特定功能的一段独立小程序,也称方法. 函数的格式 1: 修饰符 返回值类型 函数名(参数类型 形式参数1,参数类型 形式参数2,) 2: { 3: 执行语句; 4: retu ...

  6. NOIP 2013 花匠

    有多种方案,找拐点数目最简单O(n) 注意此题有相邻点价值一样,代码改变一点 #include <cstdio> #include<iostream> #include< ...

  7. cloudstack安装篇1-linux命令修改IP信息

    方式一:   ifconfig eth0 192.168.1.18 netmask 255.255.255.0   说明:该种方式可以使改变即时生效,重启后会恢复为原来的IP   方式二:   vi ...

  8. 问题记录:spark读取hdfs文件出错

    错误信息: scala> val file = sc.textFile("hdfs://kit-b5:9000/input/README.txt") 13/10/29 16: ...

  9. SQL SERVER 导入EXCEL的存储过程

    1.先在查询分析器里执行 exec sp_configure "show advanced options",1 reconfigure exec sp_configure &qu ...

  10. POJ 3621Sightseeing Cows

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9851   Accepted: 3375 Description Farme ...