异常崩溃怎么办?
关于异常崩溃是每个App都要面对的,平时开发还好,在调试状态下遇到的问题,可以通过LogCat打印的异常日志信息进行分析处理,但是一旦App上线后,大量用户安装了你的应用,每个用户的手机大小、传感器、SDK版本都不尽相同,可能你在测试机上跑的稳稳的应用,到了客户手机上就会出现一些莫名其妙的异常,如果只是一些内存泄露的问题可能还好,最起码不会瞬间崩溃,但是如果遇到一些可以导致手机崩溃Bug的话,你让出问题的用户来复现Bug是不可能的,所以,全局异常捕获就显得很重要了,而DhccCrashLib就是一个全局异常捕获的组件。
DhccCrashLib怎么用?
使用方法还是比较简单的,首先在项目的根目录下的build.gradle中加入Jcenter仓库:
1 | repositories { |
然后在你的项目的build.gradle中添加依赖:
1 | implementation 'com.dhcc.crashlib:CrashLib:1.0.3' |
这四个依赖都需要加,因为担心版本冲突,所以我在组件中使用的依赖方式是compileOnly,那么你在你的项目中如果有引用除了CrashLib外的这三个依赖的话,就可以换成你自己的版本号即可。
使用方式 在你项目的自定义Application中:
1 | public class MyApplication extends Application { |
就这么简单,首先先把你的发送邮箱和接收邮箱的相关信息都配置到EmailConfigBean中去,然后再调用LogCenter初始化相关参数即可,不过这里有一个细节需要讲一下,注意看TestCollectInfo()这个方法:
1 | public class TestCollectInfo implements ICollector { |
由于每个项目不同,可能需要采集的异常信息外的其他一些手机信息都不尽相同,我这里在源码中只设计了Key为deviceInfo和Key为exceptionInfo的两种捕获信息,deviceInfo主要是为了捕获手机信息的而exceptionInfo就是捕获异常崩溃信息的了,如果你的项目中还需要捕获其他类型的信息,可以通过实现ICollector接口来定义自己想提交的采集信息即可,记得在初始化时调用.strategy(new TestCollectInfo(), “网络属性的Key”)将采集信息传入即可。
面临的问题
在网上可以看到很多类似于全局捕获异常发送服务器或者发送邮件给指定邮箱的功能,但是这些文章都没有实际的深入场景,只是写出了逻辑代码,这样就会面临到一个很实际的问题:
异常发生时,我们要做的是将异常信息和一些其他捕获到的手机信息或上传服务器或通过邮件发送给指定邮箱,但是如果这个时间过长,导致App已经退出,进程退出后,此进程的线程也不复存在,那么如果你要做的逻辑操作还没做完,那么你这次异常的捕获就是失败的。
基于这个原因,我在异常发生时做的操作是这样的:
- 捕获异常并写入本地异常捕获文件;
- 给写入文件的操作加入回调接口,告知主线程异常写入完毕;
- 将异常信息、异常文件路径、手机设备信息等参数传入子进程的IntentService;
由于是子进程启动的Service进行的业务逻辑操作,就算主进程已经退出,也不会影响子进程的耗时操作,问题也就随之解决了。
配套的Express文件
你可能会纳闷了,什么是Express?这文件是干嘛的?
看过前面的部分后,你可能知道了这个组件是可以将异常信息发送给服务器的,而看这篇文章的很多可能都是移动端的开发人员,不一定懂服务端,就算懂,也未必能很快的搭建一个可以接受异常信息的服务端来测试,那么为了大家测试方便,我就把我的Express文件分享出来,如果你还不知道什么是Express或者Node.js,建议你先看这篇:
之后将你Nodejs根目录下的app.js改为:
1 | var fs = require('fs'); |
并且在同目录的文件夹:api中放入crashs.json:
1 | [ |
然后启动服务:
1 | 在Cmd下输入: |
之后在移动端,我们就可以设置成一下代码来捕获我们的异常信息了:
1 | ... |
这里注意.strategy(new TestCollectInfo(), “testInfo”)的testInfo,其实就是app.js中的req.body.testInfo和crashs.json中的testInfo字段。
整体设计架构
源码就不细说了,大家可以自己去看,有什么问题可以给我留言,谢谢你看完。