Android 收集崩溃信息并上传

标签: android崩溃   169人阅读  评论(0)  收藏  举报   分类: 项目相关(10) 

对于任何应用程序而言,线上崩溃都是不可避免的。毕竟完全依靠测试同学的测试,是无法测试出所有问题的。 
所以收集线上应用崩溃的信息,并上传到服务器就显得格外重要了。

收集崩溃信息并上传的步骤: 
1 收集崩溃信息并保存 
2 应用崩溃后如何处理 
3 下次启动发送崩溃信息

这里导致崩溃的异常为Java Exception,即UnChecked Exception。还有一个Native异常这里先不做讨论。 
能够引起App Crash的为UnChecked Exception(即我们通常说的RunTime 异常), 
理论上来说我们可以利用try cache将异常捕获。 
但是我们不能将所有的代码全部try cache,而且除非我们特意抛出RunTime异常,否则当异常发生时,我们是不知道下一步逻辑该如何处理的。

如何收集?

当UnChecked异常发生时,系统会通知接口UncaughtExceptionHandler,回调uncaughtException()方法。 
我们可以利用其回调的参数,收集异常的堆栈信息。

代码 1public static class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {        private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;        public UnhandledExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {            this.uncaughtExceptionHandler = uncaughtExceptionHandler;        }        @Override        public void uncaughtException(Thread thread, Throwable ex) {            //收集异常信息        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
代码 2:/**     * 收集异常信息     * @param throwable     */    private static void getStackTraceInfo(Throwable throwable) {        Writer wr = new StringWriter();        PrintWriter pwr = new PrintWriter(wr);        throwable.printStackTrace(pwr);        //将崩溃堆栈信息保存到SharedPreferences中        SPHelper.getInstance().setString(SPConstant.LAST_ERROR_REPORT, wr.toString());    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

当异常发生时,会调用终止当前线程,并通知UncaughtExceptionHandler接口,如果没有显示设置handler,系统会通知默认的Handler. 
我们要捕获当前线程的崩溃信息,需要设置为当前线程设置handler。

即调用接口: 
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

我们可以看一下这个接口的说明: 
Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, 
and no other handler has been defined for that thread.

即这个接口是针线程的。 
一般我们会监控UI线程。所以我们可以在Application onCreate()方法中将其设置进去。

代码 3Thread.setDefaultUncaughtExceptionHandler(new UnhandledExceptionHandler(Thread.getDefaultUncaughtExceptionHandler()));
  • 1
  • 2
  • 1
  • 2

那么我们为什么要传入defaultUncaughtExceptionHandler 的实例呢?

因为我们显示的设置了Handler,异常不会走Android的默认异常设置,这里传入defaultUncaughtExceptionHandler 是希望当我们收集完异常信息后, 
依然希望调用Android默认的异常处理,即杀死进程,防止出现进程不可交互的状态。 
这里便是我们之前说的第二布,崩溃之后的处理。崩溃之后收集好堆栈信息,依然走Android默认处理逻辑。

完整如下: 
代码 4:

public class CrashReporter {    public static class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {        private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;        public UnhandledExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {            this.uncaughtExceptionHandler = uncaughtExceptionHandler;        }        @Override        public void uncaughtException(Thread thread, Throwable ex) {            try {                //收集崩溃信息                getStackTraceInfo(ex);            }finally {                //走Android默认的崩溃处理逻辑                uncaughtExceptionHandler.uncaughtException(thread, ex);            }        }    }    /**     * 收集异常信息     * @param throwable     */    private static void getStackTraceInfo(Throwable throwable) {        Writer wr = new StringWriter();        PrintWriter pwr = new PrintWriter(wr);        throwable.printStackTrace(pwr);        //将崩溃堆栈信息保存到SharedPreferences中        SPHelper.getInstance().setString(SPConstant.LAST_ERROR_REPORT, wr.toString());    }    public void report() {        //上传崩溃信息    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

最后在应用下次启动时,可以调用report()方法,上传崩溃信息。当然可能还需要同时上传一些手机型号,系统版本等相关信息。

更多相关文章

  1. [置顶] Android异步更新UI-线程池-Future-Handler实例分析
  2. android读取apk中已经存在的数据库信息
  3. 第十一章、Android的线程和线程池
  4. Android中的线程模型,
  5. [转载]Android中的线程模型
  6. [Android分享] Android 得到已安装的应用程序信息
  7. android异步线程利用Handler将消息发送至UI线程

随机推荐

  1. 干货 | 51单片机最小系统电路设计
  2. 跨境支付成为第三方支付企业新战场
  3. 无法通过CITRIX STUDIO删除XenDesktop中
  4. 为何说微软不可能断供中国?因为损失可能是
  5. CDH集群大致架构流程图
  6. Python之字符编码
  7. 【css入门】css盒模型及css定位的常用属
  8. php类的引用与mysql基础
  9. 0324作业-flex布局
  10. 【CSS入门】前端布局神器Flex弹性盒模型