android崩溃日志收集和处理

    android的崩溃很常见,我们往往通过日志收集避免下次更新的重复出错。

    android的崩溃发生后通常是由:

     Thread.UncaughtExceptionHandler  

     这个类进行处理的,那么我们要收集日志就要继承这个类进行一些处理即可。

    当我们继承后,有个方法必须要我们重写,那就是:

@Override

public void uncaughtException(Thread thread, Throwable throwable) {

}

    当崩溃发生时,这个类就会调用这个方法进行处理,默认处理是手机卡住,然后几个键失灵,然后出现崩溃或者程序无响应对话框告诉你程序已经崩溃。

    但是现在我们要做处理了,我这里用到了三个类:

1:ErrorCaught     继承刚才说的类,也就是Thread.UncaughtExceptionHandler

2:ErrorHandle     看单词就知道,错误处理,那么当上面的错误发生后,一些操作是在这里面进行的,可能包含错误上传,保存这样的

3:CrashInforMationDetail    这个看单词也容易知道意思,具体的错误信息,意思就是我们手机的错误日志就要从这里面拿

    好了,分配好任务,下面开始具体的操作

    按顺序来,先说第一个类:ErrorCaught, 继承了Thread.UncaughtExceptionHandler,那重点自然是看uncaughtException这个方法的具体操作,贴出代码:

//异常崩溃发生时调用的方法,这里面开始我们想要的操作,包括日志的手机和上传等

@Override

public void uncaughtException(Thread thread, Throwable throwable) {

errHandle.excute(thread, throwable);

}

    出现了一个errHandle,不认得?不要紧,这就是我们上面说的第二个类,那么这里我们可以看到就是当崩溃发生时,我们调用了第二个类的一个方法,但是我们看到这里没有给errHandle初始化,那我们再看看第一个类:ErrorCaught的构造器

private ErrorHandleerrHandle;

//设置本程序的异常崩溃由此类处理

public ErrorCaught(Application context){

Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

errHandle =new ErrorHandle(context , uncaughtExceptionHandler);

Thread.setDefaultUncaughtExceptionHandler(this);

}

    很简单的一个构造器,就传了一个Context,但是有两行代码看不懂,中间的第二个类用构造器初始化大家应该看的懂吧,那么就说

Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

Thread.setDefaultUncaughtExceptionHandler(this);

    这俩行的意思就是设置当前程序的崩溃类为这个类,也就是把原本系统捕捉崩溃的类的工作给代替了,这里我们是要写上的。

    那这第一个类的重点就很明显了,就是errHandle.excute(thread, throwable),我们去看看这个所谓的错误处理的类,到底是怎么处理崩溃这个事情的,打开这个类,我们看我们excute这个方法干了啥,

//用来执行崩溃时具体的操作

public void excute(Thread thread, Throwable throwable) {

CrashInforMationDetail crashInforMationDetail = CrashInforMationDetail.produce(throwable, thread,context);

crashInforMationDetail.writeToFile(crashFile);

signOut(thread, throwable);

}

    厉害了哈,这么快我们的第三个类就登场了,从代码中我们大概能看出,初始化了我们的第三个类,然后调用了writeToFile这个方法,很明显crashFile是一个文件,那这里的意思就是把错误的信息写到一个文件里面的,最后的signOut(thread, throwable);也容易看出来,退出程序,那思路就很明确了,当程序崩溃时,我们调用了我们捕捉崩溃的类,然后在捕捉崩溃的方法里面做了两件事,一:是保存错误信息,二:推出程序,和我们平时崩溃的不一样的就在通常程序崩溃了就没了,但是我们的不一样,就是做了日志保存处理,嗯,很智能。

接着说第二个类吧,这个signOut方法是退出程序,我们看看代码:

//强制退出软件

public void signOut(Thread thread, Throwable throwable) {

if (uncaughtExceptionHandler !=null) {

uncaughtExceptionHandler.uncaughtException(thread, throwable);

}else {

android.os.Process.killProcess(android.os.Process.myPid());

System.exit(1);

}

}

    又发现了我们第一个类的身影,它在这干啥,我们加了一个判断如果第一个类没有捕捉到崩溃异常处理,我们这里就把这个异常又交给系统去,如果获取本地崩溃的捕捉类,那就我们自己处理。还记得我们第一个类的构造器怎么写的么?里面有这俩行代码:

Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

errHandle =new ErrorHandle(context , uncaughtExceptionHandler);

 看到没,我们第二个类获取的uncaughtExceptionHandler,是从第一个类来的,所以这里的处理就是没有一就没有二的意思。

android.os.Process.killProcess(android.os.Process.myPid());

System.exit(1);

    这俩行代码的意思就杀掉进程,退出程序。

    我们再看第一个类的构造器:

public ErrorHandle(Application context, Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {

this.context = context;

this.uncaughtExceptionHandler = uncaughtExceptionHandler;

if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

File file =new File(Environment.getExternalStorageDirectory(),"crashCollection");

if (!file.exists()) {

file.mkdirs();//创建崩溃捕捉所在文件夹

        }

crashFile =new File(file, getCrashFileName());

if (!crashFile.exists()) {

try {

crashFile.createNewFile();//创建崩溃捕捉文件

            }catch (IOException e) {

e.printStackTrace();

}

}

}

}

    意图大概很明确,是一个创建文件夹和文件的过程,那肯定就是创建崩溃日志的收集文件夹和文件。当然啦,我们要先检查有没有去权限等操作。看这个:getCrashFileName(),我们没找到是啥是吧,就是确定我们文件名的方法,给出代码:

//获取崩溃文件名称,具体是年月日组成的文件名

private String getCrashFileName() {

StringBuilder stringBuilder =new StringBuilder();

Calendar calendar = Calendar.getInstance();

int year = calendar.get(Calendar.YEAR);

int month = calendar.get(Calendar.MONTH);

int date = calendar.get(Calendar.DATE);

stringBuilder.append("crash_");

stringBuilder.append(year +"-");

stringBuilder.append(month +"-");

stringBuilder.append(date);

stringBuilder.append(".txt");

return stringBuilder.toString();

}

     下面说第三个类

CrashInforMationDetail    用来采集错误信息的类,那么这里就是需要根据不同的需求来进行获取不同的信息,但是一般会包括俩种信息,

1:手机设备的信息;2:崩溃产生的错误信息

根据第一个错我这里写的有如下:

//获取手机的一些设备参数

public static String getSysytemInfor() {

StringBuffer sb =new StringBuffer();

sb.append("主板:" +Build.BOARD +"\n");

sb.append("系统启动程序版本号:" +Build.BOOTLOADER +"\n");

sb.append("系统定制商:" +Build.BRAND +"\n");

sb.append("cpu指令集:" +Build.CPU_ABI +"\n");

sb.append("cpu指令集2:" +Build.CPU_ABI2 +"\n");

sb.append("设置参数:" +Build.DEVICE +"\n");

sb.append("显示屏参数:" +Build.DISPLAY +"\n");

sb.append("无线电固件版本:" +Build.getRadioVersion() +"\n");

sb.append("硬件识别码:" +Build.FINGERPRINT +"\n");

sb.append("硬件名称:" +Build.HARDWARE +"\n");

sb.append("HOST:" +Build.HOST +"\n");

sb.append("修订版本列表:" +Build.ID +"\n");

sb.append("硬件制造商:" +Build.MANUFACTURER +"\n");

sb.append("版本:" +Build.MODEL +"\n");

sb.append("硬件序列号:" +Build.SERIAL +"\n");

sb.append("手机制造商:" +Build.PRODUCT +"\n");

sb.append("描述Build的标签:" +Build.TAGS +"\n");

sb.append("TIME:" +Build.TIME +"\n");

sb.append("builder类型:" +Build.TYPE +"\n");

sb.append("USER:" +Build.USER +"\n");

return sb.toString();

}

    嗯,容易懂,大家可以挑着用,然后就是错误信息,这个错误信息我们是从Throwable里面取出来的:

print.append(throwable.getMessage()).append("\n");

StackTraceElement[] stackTrace = throwable.getStackTrace();

try {

for (int i =0; i < stackTrace.length; i++) {

StackTraceElement stackTraceElement = stackTrace[i];

String trace = stackTraceElement.toString();

print.append(trace +"\n");

crashInfor += trace +"\n";

}

}catch (Exception e) {

e.printStackTrace();

}

    只要我们有获取到了Throwable,这些信息全都可以拿到,包括错误的具体位置,那么我们看第三个类的构造器是什么样的,

public static CrashInforMationDetail produce(Throwable throwable, Thread thread, Context context) {

}

    里面有Throwable这个参数,也就是说第三类被调用的时候,我们就获取到了Throwable,那么这些错误信息我们就已经拿到了,然后再调用:

public void writeToFile(File file) {

PrintWriter printer =null;

try {

BufferedOutputStream out =new BufferedOutputStream(new FileOutputStream(file,true));

printer =new PrintWriter(out);

printer.println(crashInfor);

printer.flush();

}catch (IOException e) {

e.printStackTrace();

}finally {

if (printer !=null) {

printer.close();

}

}

}

    把错误信息调到第二个类中进行存储成文件,下次程序重新进入的时候就可以上传这些错误文件了,我这里写的三类的怎么使用呢?大家只需要在自己的程序里面初始化第一个类就行了,也就是new一个:new ErrorCaught(this),就可以使用崩溃收集的功能了,不过要注意的就是存储权限要给到。

    好了,大概崩溃的发生和收集想必大家也是比较清晰了,我这里没有写上传的部分,因为上传的网络框架很多,大家可以根据自己的喜欢去挑选即可,重要的是知道这是怎么一个过程就行了,好了,今天的内容就说到这,咱们下次再见...

代码点我:代码:android崩溃日志收集和处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容