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崩溃日志收集






2 0
原创粉丝点击