当前位置:   article > 正文

android崩溃日志收集和处理

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

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

Thread.UncaughtExceptionHandler复制代码

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

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

  1. @Override
  2. public void uncaughtException(Thread thread, Throwable throwable) {
  3. }
  4. 复制代码

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

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

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

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

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

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

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

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

  1. @Override
  2. public void uncaughtException(Thread thread, Throwable throwable) {
  3. errHandle.excute(thread, throwable);
  4. }
  5. 复制代码

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

  1. private ErrorHandleerrHandle;
  2. //设置本程序的异常崩溃由此类处理
  3. public ErrorCaught(Application context){
  4. Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
  5. errHandle =new ErrorHandle(context , uncaughtExceptionHandler);
  6. Thread.setDefaultUncaughtExceptionHandler(this);
  7. }
  8. 复制代码

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

  1. Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
  2. Thread.setDefaultUncaughtExceptionHandler(this);
  3. 复制代码

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

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

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

  1. public void excute(Thread thread, Throwable throwable) {
  2. CrashInforMationDetail crashInforMationDetail = CrashInforMationDetail.produce(throwable, thread,context);
  3. crashInforMationDetail.writeToFile(crashFile);
  4. signOut(thread, throwable);
  5. }
  6. 复制代码

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

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

//强制退出软件

  1. public void signOut(Thread thread, Throwable throwable) {
  2. if (uncaughtExceptionHandler !=null) {
  3. uncaughtExceptionHandler.uncaughtException(thread, throwable);
  4. }else {
  5. android.os.Process.killProcess(android.os.Process.myPid());
  6. System.exit(1);
  7. }
  8. }
  9. 复制代码

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

  1. Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
  2. errHandle =new ErrorHandle(context , uncaughtExceptionHandler);
  3. 看到没,我们第二个类获取的uncaughtExceptionHandler,是从第一个类来的,所以这里的处理就是没有一就没有二的意思。
  4. android.os.Process.killProcess(android.os.Process.myPid());
  5. System.exit(1);
  6. 这俩行代码的意思就杀掉进程,退出程序。
  7. 我们再看第一个类的构造器:
  8. public ErrorHandle(Application context, Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
  9. this.context = context;
  10. this.uncaughtExceptionHandler = uncaughtExceptionHandler;
  11. if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
  12. File file =new File(Environment.getExternalStorageDirectory(),"crashCollection");
  13. if (!file.exists()) {
  14. file.mkdirs();//创建崩溃捕捉所在文件夹
  15. }
  16. crashFile =new File(file, getCrashFileName());
  17. if (!crashFile.exists()) {
  18. try {
  19. crashFile.createNewFile();//创建崩溃捕捉文件
  20. }catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }
  26. 复制代码

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

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

  1. private String getCrashFileName() {
  2. StringBuilder stringBuilder =new StringBuilder();
  3. Calendar calendar = Calendar.getInstance();
  4. int year = calendar.get(Calendar.YEAR);
  5. int month = calendar.get(Calendar.MONTH);
  6. int date = calendar.get(Calendar.DATE);
  7. stringBuilder.append("crash_");
  8. stringBuilder.append(year +"-");
  9. stringBuilder.append(month +"-");
  10. stringBuilder.append(date);
  11. stringBuilder.append(".txt");
  12. return stringBuilder.toString();
  13. }
  14. 下面说第三个类
  15. CrashInforMationDetail 用来采集错误信息的类,那么这里就是需要根据不同的需求来进行获取不同的信息,但是一般会包括俩种信息,
  16. 1:手机设备的信息;2:崩溃产生的错误信息
  17. 根据第一个错我这里写的有如下:
  18. //获取手机的一些设备参数
  19. public static String getSysytemInfor() {
  20. StringBuffer sb =new StringBuffer();
  21. sb.append("主板:" +Build.BOARD +"\n");
  22. sb.append("系统启动程序版本号:" +Build.BOOTLOADER +"\n");
  23. sb.append("系统定制商:" +Build.BRAND +"\n");
  24. sb.append("cpu指令集:" +Build.CPU_ABI +"\n");
  25. sb.append("cpu指令集2:" +Build.CPU_ABI2 +"\n");
  26. sb.append("设置参数:" +Build.DEVICE +"\n");
  27. sb.append("显示屏参数:" +Build.DISPLAY +"\n");
  28. sb.append("无线电固件版本:" +Build.getRadioVersion() +"\n");
  29. sb.append("硬件识别码:" +Build.FINGERPRINT +"\n");
  30. sb.append("硬件名称:" +Build.HARDWARE +"\n");
  31. sb.append("HOST:" +Build.HOST +"\n");
  32. sb.append("修订版本列表:" +Build.ID +"\n");
  33. sb.append("硬件制造商:" +Build.MANUFACTURER +"\n");
  34. sb.append("版本:" +Build.MODEL +"\n");
  35. sb.append("硬件序列号:" +Build.SERIAL +"\n");
  36. sb.append("手机制造商:" +Build.PRODUCT +"\n");
  37. sb.append("描述Build的标签:" +Build.TAGS +"\n");
  38. sb.append("TIME:" +Build.TIME +"\n");
  39. sb.append("builder类型:" +Build.TYPE +"\n");
  40. sb.append("USER:" +Build.USER +"\n");
  41. return sb.toString();
  42. }
  43. 复制代码

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

  1. print.append(throwable.getMessage()).append("\n");
  2. StackTraceElement[] stackTrace = throwable.getStackTrace();
  3. try {
  4. for (int i =0; i < stackTrace.length; i++) {
  5. StackTraceElement stackTraceElement = stackTrace[i];
  6. String trace = stackTraceElement.toString();
  7. print.append(trace +"\n");
  8. crashInfor += trace +"\n";
  9. }
  10. }catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. 复制代码

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

  1. public static CrashInforMationDetail produce(Throwable throwable, Thread thread, Context context) {
  2. }
  3. 复制代码

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

  1. public void writeToFile(File file) {
  2. PrintWriter printer =null;
  3. try {
  4. BufferedOutputStream out =new BufferedOutputStream(new FileOutputStream(file,true));
  5. printer =new PrintWriter(out);
  6. printer.println(crashInfor);
  7. printer.flush();
  8. }catch (IOException e) {
  9. e.printStackTrace();
  10. }finally {
  11. if (printer !=null) {
  12. printer.close();
  13. }
  14. }
  15. }
  16. 复制代码

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

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

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

  1. 复制代码


转载于:https://juejin.im/post/5a5419de6fb9a01cbd587463

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/292503
推荐阅读
相关标签
  

闽ICP备14008679号