今天是圣诞节,首先祝大家圣诞节快乐!我们都知道一个在好的应用,上线以后在所难免也会有bug存在,有bug很正常,但是出了bug,你没有及时修复,这就比较尴尬了,轻则你会遭到领导的批评,而重责则会影响用户的使用,从而流失一批客户群,所以啊,监控bug的出现,并及时修复,也是开发当中很重要的一步。
Android发展到今天,对于bug的收集及监控,早已涌现出了很多出色的第三方平台,比如,百度,友盟,阿里,bugtags等等,提供很方便的接入方法,这些第三方平台,像bugtags,在收集应用的bug时,就显的比较及时,而且相关信息,包括,操作步骤,所用手机型号,及bug位置等等,捕获的很是全面,而且还支持在线提bug,给测试人员提供很大的方便,但是,很不幸的是它是收费的,如果想免费的话,可以使用友盟,友盟也是一个不错的收集bug平台。
毕竟第三方不是自己的,那么,在不用第三方的情况下,我们该如何收集和监控bug呢?
我们都知道,当应用发生crash时,系统就会kill掉正在执行的程序,其实说白了就是应用闪退或者说崩溃了,对于这种崩溃,还好,Android还比较仁慈,给我们提供了处理这种异常的方式,我们打开Thread这个类的源码,我们会看到这样一个方法:
/**
* Sets the default uncaught exception handler. This handler is invoked in
* case any Thread dies due to an unhandled exception.
*
* @param handler
* The handler to set or null.
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
Thread.defaultUncaughtHandler = handler;
}
对以上的代码,我们不难看出,当应用出现了crash之后,系统会默认调出UncaughtExceptionHandler的uncaughtException方法,在此方法里我们就可以捕获到相关异常,把它存到sd卡或者上传到服务端,也是也是一件特别简单的事,想必大多数人已经知道了,无非就是去实现UncaughtExceptionHandler,然后在uncaughtException方法里捕获异常,最后再调用Thread的setDefaultUncaughtExceptionHandler()方法来设置线程默认的异常处理器,那么久可以轻松捕获异常了,来看一下例子吧:
/**
* Created by xiaoming.li on 16/12/25.
* 异常捕获工具类
*/
public class CrashHandlerUtils implements Thread.UncaughtExceptionHandler {
private static CrashHandlerUtils mInstance = new CrashHandlerUtils();
private Thread.UncaughtExceptionHandler mDefaultHandler;
private Context mContext;
private CrashHandlerUtils() {
}
public static CrashHandlerUtils getInstance() {
return mInstance;
}
/**
* 对工具类初始化
*/
public void init(Context context) {
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
mContext = context;
}
/**
* 这个方法用于捕获异常,ex就是我们捕获的异常,
* 在这里我们就可以把相关信息收集到sd卡或者上传到服务端,以便开发人员做修复
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
saveExceptionToSDcard(ex);//存到sd卡
saveExceptionToServer(ex);//保存到服务端
}
/**
* 保存到sd卡
*/
private void saveExceptionToSDcard(Throwable ex) {
//判断sd卡是否就绪,也就是是否存在,不存在久存不进去
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
return;
}
//下面就是写进sd卡了,就不写,大家可以自己来写。
}
/**
* 上传到服务端
*/
private void saveExceptionToServer(Throwable ex) {
}
/**
* 手机崩溃时的相关信息,崩溃时间,手机的相关信息,应用的信息
* 在存sd卡或者上传服务端时,可以一并上传
*/
private void getExceptionInFo() throws PackageManager.NameNotFoundException {
//获取崩溃时间
long current = System.currentTimeMillis();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
PackageManager packageManager = mContext.getPackageManager();
PackageInfo inFo = packageManager.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
int versionCode = inFo.versionCode;
String versionName = inFo.versionName;
//Android版本号:
String release = Build.VERSION.RELEASE;
int sdkInt = Build.VERSION.SDK_INT;
//手机制造商
String mobileName = Build.MANUFACTURER;
//手机型号
String model = Build.MODEL;
//CPU架构
String cpu = Build.CPU_ABI;
}
}