Android自定义错误日志收集
来源:互联网 发布:vue.js框架是干什么的 编辑:程序博客网 时间:2024/05/17 01:39
一、概述
一般做Android开发的朋友多多少少都会碰见各种各样的问题,一般都怎么解决这些bug尼?有的朋友会说Debug,但是有没有想过,万一客户上线了尼?打过电话,说软件出错了,那这个时候如果不做错误收集,那么就会无法知道发生什么问题了,这个时候就需要我们自己手动的做错误收集了。
如图:
在第二页中写了一个除0的异常,然后进入后发生异常,记录到日志并存储到Sdcard中,最后返回上一页。
二、自定义我们的异常收集类CrashHandler
** * 自定义异常处理器 * * @author 刘洋巴金 * @date 2017-4-5 * */public class CrashHandler implements UncaughtExceptionHandler{private Context mContext;private UncaughtExceptionHandler defaultUncaught;private File logFile = new File(Environment.getExternalStorageDirectory(), "crashLog.trace");public CrashHandler(Context context) {super();mContext = context; defaultUncaught = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); // 设置为当前线程默认的异常处理器}}
首先先自定义我们的CrashHandler并实现UncaughtExceptionHandler接口,并保留系统默认异常处理。
然后实现uncaughtException方法
@Overridepublic void uncaughtException(Thread thread, Throwable ex) {// 打印当前的异常信息ex.printStackTrace();// 如果我们没处理异常,并且系统默认的异常处理器不为空,则交给系统来处理if(!handlelException(ex) && defaultUncaught != null){defaultUncaught.uncaughtException(thread, ex);}else{ // 已经记录完log, 提交服务器upLoadErrorFileToServer(logFile);Intent in = new Intent(mContext, MainActivity.class);in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 如果设置了此标志,这个activity将成为一个新task的历史堆栈中的第一个activitymContext.startActivity(in);// 杀死我们的进程Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Process.killProcess(Process.myPid()); // 杀死线程}}, 2 * 1000);}}
Thread.UncaughtExceptionHandler.uncaughtException()会在线程因未捕获的异常而临近死亡时被调用。
/** * 记录异常信息 * */private boolean handlelException(Throwable ex) {// TODO Auto-generated method stubif(ex == null){return false;}PrintWriter pw = null;try {if(!logFile.exists()){logFile.createNewFile();}pw = new PrintWriter(logFile);// 收集手机及错误信息collectInfoToSDCard(pw, ex);pw.close();} catch (Exception e) {e.printStackTrace();}return true;}
正常的记录错误信息,把错误信息记录到手机卡中,如果异常为空,则把权限交给系统。
/** * 收集记录错误信息 * @throws NameNotFoundException * @throws IllegalArgumentException * @throws IllegalAccessException * */private void collectInfoToSDCard(PrintWriter pw, Throwable ex) throws NameNotFoundException, IllegalAccessException, IllegalArgumentException {// TODO Auto-generated method stubPackageManager pm = mContext.getPackageManager();PackageInfo mPackageInfo = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);pw.println("time: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); // 记录错误发生的时间pw.println("versionCode: " + mPackageInfo.versionCode); // 版本号pw.println("versionName: " + mPackageInfo.versionName); // 版本名称Field[] fields = Build.class.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);pw.print(field.getName() + " : ");pw.println(field.get(null).toString());}ex.printStackTrace(pw);}Build类,这个类定义了所有关于手机的一些参数,如版本号,系统名称,Android版本等。
然后通过反射机制,把这些信息和错误信息一起记录到日志里面。
getDeclaredFields 获取所有属性
field.setAccessible(true); 可以读取private属性并可对其进行更改
好了,错误信息都记录完毕了,最后杀死我们的进程,返回上一级页面,这样是为了用户体验
// 已经记录完log, 提交服务器upLoadErrorFileToServer(logFile);Intent in = new Intent(mContext, MainActivity.class);in.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 如果设置了此标志,这个activity将成为一个新task的历史堆栈中的第一个activitymContext.startActivity(in);// 杀死我们的进程Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {Process.killProcess(Process.myPid()); // 杀死线程}}, 2 * 1000);
当然正常的逻辑,也可以把这个记录的错误日志发到服务端
好了,最后在自定义的application中使用它吧
public class MyApplication extends Application{@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();new CrashHandler(this);}}
完事了
三、一些第三方的错误收集
1. 友盟错误统计
老牌了,可以错误收集和查看渠道。
2. TalkingData
功能和友盟差不多,支持预警功能,支持“灵动分析”,即动态添加监控事件,目前免费。
3. bugly
鹅厂出品,页面比友盟好
四、demo
Android崩溃日志收集
- Android自定义错误日志收集
- Android 日志错误收集
- android自定义view错误收集
- android自定义异常日志收集器
- android 收集错误日志 上传服务器
- 错误日志收集
- Android项目的错误异常收集日志记录
- 安卓错误日志收集
- Sentry--错误日志收集框架
- Android崩溃日志收集
- Android日志收集
- Android崩溃日志收集
- Android 日志收集
- Android Crash日志收集
- Android Crash日志收集
- PHP 自定义错误日志
- PHP 自定义错误日志
- 错误收集(本地Log日志)错误上传
- ACTIVEMQ Channel was inactive for too (>30000)long
- 恢复到特定点(时间点、scn、日志序列号),rman不完全恢复
- QClipboard 剪贴板
- 最短路径—Dijkstra算法和Floyd算法
- 学习spring mvc之路一:简单的Hello word
- Android自定义错误日志收集
- Android AutoLayout全新的适配方式
- SpringApplicationConfiguration 这个不能用 怎么办?
- RTP/RTCP基础
- 剑指offer-面试题31-连续子数组的最大和
- java实现游戏的循环及游戏帧数处理
- 网友使用过程中的一个drools的复杂问题
- Dataguard 之 移除和拆分
- 详解java设计模式(七)之享元模式(结构型)