Android自定义错误日志收集

一、概述

一般做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方法

@Override
public 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的历史堆栈中的第一个activity
		mContext.startActivity(in);
		
		// 杀死我们的进程
		Timer timer = new Timer();
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				Process.killProcess(Process.myPid()); // 杀死线程
			}
		}, 2 * 1000);
	}
}

Thread.UncaughtExceptionHandler.uncaughtException()会在线程因未捕获的异常而临近死亡时被调用。

/**
 * 记录异常信息
 * */
private boolean handlelException(Throwable ex) {
	// TODO Auto-generated method stub
	if(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 stub
		PackageManager 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的历史堆栈中的第一个activity
	mContext.startActivity(in);
			
	// 杀死我们的进程
	Timer timer = new Timer();
	timer.schedule(new TimerTask() {

		@Override
		public void run() {
			Process.killProcess(Process.myPid()); // 杀死线程
		}
	}, 2 * 1000);

当然正常的逻辑,也可以把这个记录的错误日志发到服务端

好了,最后在自定义的application中使用它吧

public class MyApplication extends Application{

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		new CrashHandler(this);
	}
}

完事了


三、一些第三方的错误收集

1. 友盟错误统计  

        老牌了,可以错误收集和查看渠道。

2. TalkingData    

       功能和友盟差不多,支持预警功能,支持“灵动分析”,即动态添加监控事件,目前免费。

3. bugly 

         鹅厂出品,页面比友盟好


四、demo

         Android崩溃日志收集






你可能感兴趣的:(【Android中级】,【Android初级】)