概述
在开发过程中,我们经常面临的问题是解决造成程序Crash的bug,而解决这些问题的途径无非是通过Crash的时候遗留的log进行分析,快速定位问题发生的原因然后解决问题。大多数时候我们都是在开发过程中进行自测的时候发现问题,这一类的问题发生的时候log信息通常都会显示在控制台上,通过简单分析基本能够得到解决,而真正难以解决的是测试人员在平时测试的时候偶然发现的一个bug,然而又不容易复现,或者是用户使用过程中产生的偶现的Crash,通常这一类问题我们都是无法直接看到Crash发生时的log信息的,解决的方法只能是按照他人提供的操作步骤机械性的进行重复操作,盼着bug能够再现……
针对以上问题,在此提出两种解决思路,当然不是能够直接解决你的Crash的万能代码,而是提供一个在别人手机上发生Crash的时候,你依旧能够获得Crash时产生的log信息,方便开发者定位问题。
针对第二种情况,用户反馈的Crash,在此推荐在你的应用程序中集成腾讯Bugly,这是一款使用十分方便的Crash跟踪工具,集成也十分简单,他们的介绍是:
一种愉悦的开发方式
腾讯Bugly,为移动开发者提供专业的异常上报,运营统计和内测分发解决方案,帮助开发者快速发现并解决异常,同时掌握产品运营动态,及时跟进用户反馈。
腾讯bugly接入首页
使用之后当用户程序由于异常产生Crash的时候,该Crash的log信息会直接上报到你注册的应用中,和在控制台中看到的Crash信息无异,同时提供其他一系列相关数据,包括产生Crash的手机型号,SDK版本等,一图胜千言:
针对第二种情况,身边测试人员反馈的Crash,或者你自己的手机未接入电脑的时候产生的Crash,这些情况下你都无法直接在控制台上看到log信息,此时提供的解决方案是将发生Crash时候的log信息直接存到手机里,该log信息以文本形式存储,可以直接打开查看,Android为我们提供了UncaughtExceptionHandler这个类来进行该操作,至于这个类的具体介绍网上有很多博文,请自行百度,在此提供工具类。可直接使用,使用方法见后文。
/**
* Created by ShiXiuwen on 2017/1/14.
* <p>
* Description:将程序的Crash信息写进文件
*/
public class Utils_CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "Util_CrashHandler";
private Context mContext;
private static Utils_CrashHandler INSTANCE = new Utils_CrashHandler();
private Thread.UncaughtExceptionHandler mDefaultHandler;
public static Utils_CrashHandler getInstance() {
return INSTANCE;
}
public void init(Context ctx) {
mContext = ctx.getApplicationContext();
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(final Thread t, final Throwable e) {
try {
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
Throwable cause = e.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
File file = new File(getDiskCacheDir(mContext, "crash"), "crash.log");
if (file.exists() && file.length() > 5 * 1024 * 1024) { // <5M
boolean delete = file.delete();
}
File folder = new File(getDiskCacheDir(mContext, "crash"));
if (folder.exists() && folder.isDirectory()) {
if (!file.exists()) {
boolean newFile = file.createNewFile();
if(!newFile){
return;
}
}
} else {
boolean mkDir = folder.mkdir();
if (mkDir) {
boolean newFile = file.createNewFile();
if(!newFile){
return;
}
}
}
FileOutputStream fos = new FileOutputStream(file, true);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
String format = sdf.format(new Date());
byte[] bytes = (format + //追加Crash时间
"n" + result + //Crash内容
"n" + "######## ~~~ T_T ~~~ ########" + //分割线
"n").getBytes();
fos.write(bytes);
fos.flush();
fos.close();
} catch (Exception exception) {
exception.printStackTrace();
}
mDefaultHandler.uncaughtException(t, e); //该代码不执行的话程序无法终止
}
/**
* @param context context
* @param dirName dirName
* @return dir
*/
private String getDiskCacheDir(Context context, String dirName) {
String cachePath = null;
if ("mounted".equals(Environment.getExternalStorageState())) {
File externalCacheDir = context.getExternalCacheDir();
if (externalCacheDir != null) {
cachePath = externalCacheDir.getPath();
}
}
if (cachePath == null) {
File cacheDir = context.getCacheDir();
if ((cacheDir != null) && (cacheDir.exists())) {
cachePath = cacheDir.getPath();
}
}
//0/emulate/Android/data/data/com.***.***/crash/crash.log
return cachePath + File.separator + dirName;
}
}
使用方法
在程序的Application类中,直接注册一句代码即可,eg:
/**
* Created by ShiXiuwen on 2017/1/14.
* <p>
* Description:Application 初始化操作
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//初始化CrashHandler收集崩溃信息到本地
Utils_CrashHandler.getInstance().init(this);
}
}
使用该工具类之后,手机到的Crash信息会被保存在手机的缓存目录中,比如你的项目包名为:
com.mycompanyname.demo
则log文件在手机中的存储路径为:
//0/emulate/Android/data/data/com.mycompanyname.demo/crash/crash.log
不同时间发生的Crash都会保存到该文件中,和控制台中输出的log信息无异。
其实在实际开发过程中还会遇到另外一种情况,那就是系统底层发生Crash,比如你调用了JNI文件而产生的Crash,有时候即使你的手机连接在控制台上也无法打印出log信息,因为该这类Crash发生的时候很可能相关进程会直接被kill掉,导致AndroidStudio清楚了控制台上的log信息,该情况下提供的解决思路是打开系统控制台,使用adb logcat命令抓取你想要的log,这样能够保证log不会被清除,不过该方法信息量有点大,要加上合适的过滤条件或者准确的控制开始及结束来定位(操作之前开始打印log,发生Crash的时候立即按Ctrl+C停止log打印),再或者配合log的时间标识记住大概产生Crash的时候log的打印时间,以此定位具体log信息。adb logcat的具体使用方法推荐博客:
http://blog.csdn.net/tumuzhuanjia/article/details/39555445
以上是本人使用过的log收集方法,如客官您有更好的建议,欢迎留言告知,当感激不尽~
最后
以上就是听话雪糕为你收集整理的Android客户端收集Crash信息的常用方法的全部内容,希望文章能够帮你解决Android客户端收集Crash信息的常用方法所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复