在Android手机上保存Crash Log

  1. 定义CrashLog文件:如果有存储器,则将文件保存在存储器下。否则保存在data目录下。存储器不一定是SD卡,也可能是mount出来的一块存储空间(不是内存)。比如,小米3就没有SD卡。

    public class CrashLog {
     private static Context mContext;
     public static final String DIR_FOR_APP = "myApp";
     public static final String FILE_NAME_FOR_CRASH__LOG = "crash.txt";
     
     public static void setContext( Context aContext ) {
      mContext = aContext.getApplicationContext();
     }
     
     public static void writeLog(String log) throws Exception {
      File dir = createFileDir(DIR_FOR_APP);
      File file = new File(dir.getPath(), FILE_NAME_FOR_CRASH__LOG);
      if(!file.exists()){
       file.createNewFile();
      }
      StringBuffer orgStr = new StringBuffer();
      FileReader fr = new FileReader(file);
      int ch = 0;
      while((ch = fr.read()) != -1) {  
       orgStr.append((char)ch);
      }
      fr.close();
      
      Calendar c = Calendar.getInstance();
      String time = String.format("%2d:", c.get(Calendar.HOUR))+
      String.format("%2d:", c.get(Calendar.MINUTE))+
      String.format("%2d", c.get(Calendar.SECOND))+" ";
      String str = orgStr.toString() + "\r\n" + time + log + "\r\n";
      FileWriter fw = new FileWriter(file);
      fw.write(str);
      fw.close();
     }
     
     public static void clearLog(){
      String dirPath = getDirPath(DIR_FOR_APP);
      if( dirPath != null ) {
       File file = new File(FILE_NAME_FOR_CRASH__LOG);
       if(file.exists()){
        file.delete();
       }
      }
     }
     
      public static String getDirPath(String dirName){
       String filePath = null;
       String state = Environment.getExternalStorageState();
       if (state.equals(Environment.MEDIA_MOUNTED)) {
        // 如果有存储器,则返回存储器的路径
        filePath = Environment.getExternalStorageDirectory()
          + File.separator + dirName;
       } else {// 否则返回data目录的路径
        filePath = mContext.getCacheDir().getPath() + File.separator
          + dirName;
       }
       return filePath;
      }
         
      public static File createFileDir(String dirName) {
       String filePath = getDirPath(dirName);
       if( filePath == null ) {
        return null;
       }
       File destDir = new File(filePath);
       if (!destDir.exists()) {
        destDir.mkdirs();
       }
       return destDir;
      }
    }

    2. 定义CrashHandler异常捕获类:当程序抛出异常后,由CrashHandler先捕获。将异常堆栈信息和手机系统信息打印到手机制定位置的log文件后,退出。

public class CrashHandler implements UncaughtExceptionHandler {
    private Context mContext;
    private static CrashHandler mInstance = null;
    // 系统默认的异常处理(默认情况下,系统会终止当前的异常程序)
    private UncaughtExceptionHandler mDefaultCrashHandler;
 
    private CrashHandler(Context c) {
        // 获取系统默认的异常处理器
        mDefaultCrashHandler = Thread
                .getDefaultUncaughtExceptionHandler();
        // 将当前实例设为系统默认的异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
        // 获取Context,方便内部使用
        mContext = c.getApplicationContext();
    }
    public synchronized static CrashHandler create(Context cxt) {
        if (mInstance == null) {
            mInstance = new CrashHandler(cxt);
        }
        return mInstance;
    }
/**
 * 当UncaughtException发生时会回调该函数来处理
 */
 @Override
 public void uncaughtException(Thread thread, Throwable ex) {
      // TODO Auto-generated method stub
      StringBuffer logInfo = new StringBuffer();
      logInfo.append("Exception: ");
      logInfo.append(ex.getMessage());
      logInfo.append("\r\n");
      logInfo.append(getStackMsg(ex));
      logInfo.append("Phone informations:");
      logInfo.append("\r\n");
      try {
           logInfo.append(getPhoneInfo());
            // 导出异常信息到存储器中
           CrashLog.writeLog(logInfo.toString());
      } catch (Exception e) {
       //忽略异常
      } finally {
       // 如果系统提供了默认的异常处理器,则交给系统去结束程序,
       if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, ex);
       } else {
            MyApplication.getInstance().exit();
       }
    }
 }
   
 private static String getStackMsg(Throwable e) {  
      StringBuffer sb = new StringBuffer();  
      StackTraceElement[] stackArray = e.getStackTrace();  
      for (int i = 0; i < stackArray.length; i++) {  
          StackTraceElement element = stackArray[i];  
          sb.append(element.toString() + "\r\n");
      }  
      return sb.toString();
 } 
 private String getPhoneInfo()
            throws NameNotFoundException {
       StringBuffer info = new StringBuffer();
  
        // 应用的版本号
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(),
                PackageManager.GET_ACTIVITIES);
        info.append("App Version Name: ");
        info.append(pi.versionName);
        info.append("\r\n");
        // android版本号
        info.append("OS Version: ");
        info.append(Build.VERSION.RELEASE);
        info.append("_");
        info.append(Build.VERSION.SDK_INT);
        info.append("\r\n");
        // 手机制造商
        info.append("Vendor: ");
        info.append(Build.MANUFACTURER);
        info.append("\r\n");
        // 手机型号
        info.append("Model: ");
        info.append(Build.MODEL);
        info.append("\r\n");
        // cpu架构
        info.append("CPU ABI: ");
        info.append(Build.CPU_ABI);
        info.append("\r\n");
        
        return info.toString();
    }
}

3. 自定义Application类,初始化CrashLog和CrashHandler,并提供完全退出应用的接口exit()。

public class MyApplication extends Application{
 // 单例模式
 private static MyApplication mAppInstance;
 // Activity容器
 private List<Activity> mActivityList = new LinkedList<Activity>();
 
 public MyApplication(){ 
 }
 
 public static MyApplication getInstance() {
  if( mAppInstance == null ) {
   mAppInstance = new MyApplication();
  }
  return mAppInstance;
 }
 
 // 每新建一个Activity,都要添加到容器中
 public void addActivity(Activity a){
  mActivityList.add(a);
 }
 
 // 遍历容器中所有Activity并finish
 public void exit(){
     for (Activity activity : mActivityList) {  
         activity.finish();  
     }  
     System.exit(0);  
  }
 @Override
 public void onCreate() {
     super.onCreate();
     CrashLog.setContext(this);
     CrashHandler.create(this);
 }
}

转载于:https://my.oschina.net/u/1984976/blog/371146

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值