CrashHandler.java
UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告
package  com.amanda;
import  java.io.File;
import  java.io.FileOutputStream;
import  java.io.PrintWriter;
import  java.io.StringWriter;
import  java.io.Writer;
import  java.lang.Thread.UncaughtExceptionHandler;
import  java.lang.reflect.Field;
import  java.text.DateFormat;
import  java.text.SimpleDateFormat;
import  java.util.Date;
import  java.util.HashMap;
import  java.util.Map;
import  android.content.Context;
import  android.content.pm.PackageInfo;
import  android.content.pm.PackageManager;
import  android.content.pm.PackageManager.NameNotFoundException;
import  android.os.Build;
import  android.os.Environment;
import  android.os.Looper;
import  android.util.Log;
import  android.widget.Toast;
/**
 * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
 * 
 *  @author  user
 * 
 */
public   class   CrashHandler   implements  UncaughtExceptionHandler {
    
     private   static   final  String  TAG  =  "CrashHandler" ;
     private   static   final  String  CRASH_FLOD_NAME  =  "crash" ;
    
     //系统默认的UncaughtException处理类 
     private  Thread.UncaughtExceptionHandler  mDefaultHandler ;
     //CrashHandler实例
     private   static   CrashHandler   INSTANCE  =  new   CrashHandler ();
     //程序的Context对象
     private  Context  mContext ;
     //用来存储设备信息和异常信息
     private  Map<String, String>  infos  =  new  HashMap<String, String>();
     //用于格式化日期,作为日志文件名的一部分
     private  DateFormat  formatter  =  new  SimpleDateFormat( "yyyyMMdd_kkmmss" );
     /** 保证只有一个CrashHandler实例 */
     private  CrashHandler() {
    }
     /** 获取CrashHandler实例 ,单例模式 */
     public   static   CrashHandler  getInstance() {
         return   INSTANCE ;
    }
     /**
     * 初始化
     * 
     *  @param  context
     */
     public   void  init(Context context) {
         mContext  = context;
         //获取系统默认的UncaughtException处理器
         mDefaultHandler  = Thread. getDefaultUncaughtExceptionHandler ();
         //设置该CrashHandler为程序的默认处理器
        Thread. setDefaultUncaughtExceptionHandler ( this );
    }
     /**
     * 当UncaughtException发生时会转入该函数来处理
     */
     @Override
     public   void  uncaughtException(Thread thread, Throwable ex) {
         if  (!handleException(ex) &&  mDefaultHandler  !=  null ) {
             //如果用户没有处理则让系统默认的异常处理器来处理
             mDefaultHandler .uncaughtException(thread, ex);
        }  else  {
             try  {
                Thread. sleep (3000);
            }  catch  (InterruptedException e) {
                Log. e ( TAG ,  "error : " , e);
            }
             //退出程序
            android.os.Process. killProcess (android.os.Process. myPid ());
            System. exit (1);
        }
    }
     /**
     * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
     * 
     *  @param  ex
     *  @return  true:如果处理了该异常信息;否则返回false.
     */
     private   boolean  handleException(Throwable ex) {
         if  (ex ==  null ) {
             return   false ;
        }
         //使用Toast来显示异常信息
         new  Thread() {
             @Override
             public   void  run() {
                Looper. prepare ();
                Toast. makeText ( mContext ,  "很抱歉,程序出现异常,即将退出." , Toast. LENGTH_LONG ).show();
                Looper. loop ();
            }
        }.start();
        
         //收集设备参数信息 
        collectDeviceInfo( mContext );
        
         //保存日志文件 
        saveCrashInfo2File(ex);
         return   true ;
    }
    
     /**
     * 收集设备参数信息
     *  @param  ctx
     */
     public   void  collectDeviceInfo(Context ctx) {
         try  {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager. GET_ACTIVITIES );
             if  (pi !=  null ) {
                 infos .put( "packageName" , pi. packageName );
                String versionName = pi. versionName  ==  null  ?  "null"  : pi. versionName ;
                String versionCode = pi. versionCode  +  "" ;                
                 infos .put( "versionName" , versionName);
                 infos .put( "versionCode" , versionCode);                
            }
        }  catch  (NameNotFoundException e) {
            Log. e ( TAG ,  "an error occured when collect package info" , e);
        }
        Field[] fields = Build. class .getDeclaredFields();
         for  (Field field : fields) {
             try  {
                field.setAccessible( true );
                 infos .put(field.getName(), field.get( null ).toString());
                Log. d ( TAG , field.getName() +  " : "  + field.get( null ));
            }  catch  (Exception e) {
                Log. e ( TAG ,  "an error occured when collect crash info" , e);
            }
        }
    }
     /**
     * 保存错误信息到文件中
     * 
     *  @param  ex
     *  @return     返回文件名称,便于将文件传送到服务器
     */
     private  String saveCrashInfo2File(Throwable ex) {
        
        StringBuffer sb =  new  StringBuffer();
         for  (Map.Entry<String, String> entry :  infos .entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key +  "="  + value +  "\n" );
        }
        
        Writer writer =  new  StringWriter();
        PrintWriter printWriter =  new  PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
         while  (cause !=  null ) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
         try  {
             long  timestamp = System. currentTimeMillis ();
            String time =  formatter .format( new  Date());
            String fileName =  "crash_"  + time +  "_"  + timestamp +  ".log" ;
            String fileAbsPath =  "" ;
             if  (Environment. getExternalStorageState ().equals(Environment. MEDIA_MOUNTED ) && 
                    !Environment. getExternalStorageState ().equals(Environment. MEDIA_MOUNTED_READ_ONLY )) {
                fileAbsPath = Environment. getExternalStorageDirectory ().getPath()+File. separator + CRASH_FLOD_NAME +File. separator ;
            }
             else {
                fileAbsPath =  mContext .getFilesDir().getPath()+File. separator + CRASH_FLOD_NAME +File. separator ;
            }
            
            File dir =  new  File(fileAbsPath);
             if  (!dir.exists()) {
                dir.mkdirs();
            }
            
            FileOutputStream fos =  new  FileOutputStream(fileAbsPath + fileName);
            fos.write(sb.toString().getBytes());
            fos.close();
             return  fileName;
        }  catch  (Exception e) {
            Log. e ( TAG ,  "an error occured while writing file..." , e);
        }
         return   null ;
    }
}

 
CrashApplication.java
继承Application,实现全局crash报告记录
package  com.amanda;
import  android.app.Application;
public   class   CrashApplication   extends  Application {
     @Override
     public   void  onCreate() {
         super .onCreate();
        CrashHandler crashHandler = CrashHandler. getInstance ();
        crashHandler.init(getApplicationContext());
    }
}

 
AndroidManifest.xml
<? xml   version = "1.0"   encoding = "utf-8" ?>
< manifest   xmlns:android = "http://schemas.android.com/apk/res/android"
       package = "com.amanda"
       android:versionCode = "1"
       android:versionName = "1.0" >
    
     < uses-sdk  
         android:minSdkVersion = "15"
         android:targetSdkVersion = "15" />
     < uses-permission   android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
     < application  
         android:name = ".CrashApplication"
         android:icon = "@drawable/icon"  
         android:label = "@string/app_name"
         android:allowBackup = "true" >
        
         < activity   android:name = ".MainActivity"
                   android:label = "@string/app_name"
                   android:theme = "@style/mytheme" >
             < intent-filter >
                 < action   android:name = "android.intent.action.MAIN"   />
                 < category   android:name = "android.intent.category.LAUNCHER"   />
             </ intent-filter >
         </ activity >

     </ application > </ manifest >

 
这样,就可以实现当出现UncaughtException时,将其相关信息保存到文件/sdcard/crash/xx.log或者/data/data/<package name>/file/crash/xx.log

保存全局Crash报告的更多相关文章

  1. 保存全局Crash报告&发送邮件

    上篇写到,将程序中没有处理到的crash信息保存到本地文件夹下.但是实际的情况是,你不可能总是将用户的设备拿过来.所以一般性的处理是,将crash reports发送到服务器或者邮箱.所以针对上篇的代 ...

  2. Android应用如何反馈Crash报告

    转自:http://www.cnblogs.com/draem0507/archive/2013/05/25/3099461.html 一.为什么要Crash crash可以理解成堕落,垮台.按照我们 ...

  3. ios如何生成crash报告

    #include <signal.h> #include <execinfo.h> void OnProcessExceptionHandler(int sigl) { do ...

  4. BFS(广度优先搜索遍历保存全局状态,华容道翻版做法)--08--DFS--蓝桥杯青蛙跳杯子

    题目描述 X星球的流行宠物是青蛙,一般有两种颜色:白色和黑色. X星球的居民喜欢把它们放在一排茶杯里,这样可以观察它们跳来跳去. 如下图,有一排杯子,左边的一个是空着的,右边的杯子,每个里边有一只青蛙 ...

  5. Breakpad Google的crash捕获、抓取开源库

    简介: Breadpad为google chrominum项目下用于处理dump的一套工具:内部采用跨平台方式实现捕获.生成.解析与平台无关的dump,便于统一处理:支持进程内与进程外捕获,当为进程外 ...

  6. iOS应用的crash日志的分析基础

        Outline如何获得crash日志如何解析crash日志如何分析crash日志     1. iOS策略相关     2. 常见错误标识     3. 代码bug 一.如何获得crash日志 ...

  7. Oracle AWR报告生成和性能分析

    目录 一.AWE报告生成步骤 1.1 工具选择 1.2 自动创建快照 1.3 手工创建快照 1.4 生成AWR报告 二.AWR报告分析 2.1 AWR之DB Time 2.2 AWR之load_pro ...

  8. 了解和分析iOS Crash

    WeTest 导读 北京时间凌晨一点,苹果一年一度的发布会如期而至.新机型的发布又会让适配相关的同学忙上一阵子啦,并且iOS Crash的问题始终伴随着移动开发者.本文将从三个阶段,由浅入深的介绍如何 ...

  9. 低于0.01%的极致Crash率是怎么做到的?

    WeTest 导读 看似系统Bug的Crash 99%都不是系统问题!本文将与你一起探索Crash分析的科学方法. 在移动互联网闯荡多年的iOS手机管家,经过不断迭代创新,已经涵盖了隐私(加密相册). ...

随机推荐

  1. 查看linux系统的信息

    #!/bin/sh ################################################## #function:get host's information #Autho ...

  2. WPF中ListBox的绑定

    WPF中列表式控件派生自ItemsControl类,继承了ItemsSource属性.ItemsSource属性可以接收一个IEnumerable接口派生类的实例作为自己的值(所有可被迭代遍历的集合都 ...

  3. java四舍五入BigDecimal和js保留小数点两位

    java四舍五入BigDecimal保留两位小数的实现方法: // 四舍五入保留两位小数System.out.println("四舍五入取整:(3.856)="      + ne ...

  4. jumpserver安装教程

    centos7系统一步一步安装jumpserver 参照官方文档,查找了百度所有的文档,基本上都是按照官方的文档操作的 官方文档点我-> 安装jumpserver需注意: 1:网络环境要好,有的 ...

  5. spark技术总结(1)

    1. 请描述spark RDD原理与特征 RDD为Resilient Distributed Datasets缩写,译文弹性分布式数据集. 他是spark系统中的核心数据模型之一,另外一个是DAG模型 ...

  6. MongoDB官方文档结构

    本文展示MongoDB 3.6.4.0的官方Server文档的结构图——一眼可见完整的知识脉络图.不过,MongoDB除了Server的文档外,还有DRIVERS.CLOUD.TOOLS.DUIDES ...

  7. MySQL字符集编码相关

    Windows 10家庭中文版,MySQL  5.7.20,2018-05-07 Part.1 查找数据库的字符集编码 查看MySQL字符集编码:status命令 使用命令行登录MySQL服务器,然后 ...

  8. Failed to load class "org.slf4j.impl.StaticLoggerBinder"

    调试程序出现如下错误: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: Default ...

  9. Python_oldboy_自动化运维之路(二)

    本节内容: 1.pycharm工具的使用 2.进制运算 3.表达式if ...else语句 4.表达式for 循环 5.break and continue 6.表达式while 循环 1.pycha ...

  10. UE简单配置

    1 头上显示文件位置和名称,视图->视图列表——>打开文件标签,在右面点放大 2 函数列表,视图->视图列表——>打开文件标签