Android 全局异常处理

/**
 * @类说明   app全局异常处理类
 *
 */
public class CrashHandler implements UncaughtExceptionHandler {
 public static final String TAG = "CrashHandler";
 // 系统默认的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("yyyy-MM-dd-HH-mm-ss");
 private StringBuffer sb;

 /**
  * 手机的缓存根目录
  */
 private static String mDataRootPath = null;
 /**
  * 保存奔溃日子的目录名
  */
 private final static String FOLDER_NAME = "/mycrash/";

 /**
  * sd卡的根目录
  */
 private static String mSdRootPath = Environment.getExternalStorageDirectory().getPath();

 /**
  * 获取储存的目录
  * 
  * @return
  */
 private String getStorageDirectory() {
  return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ? mSdRootPath + FOLDER_NAME : mDataRootPath
    + FOLDER_NAME;
 }
 /** 保证只有一个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);
   }

   //重启程序
   Intent intent = new Intent();
         intent.setClass(mContext,SplashActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

         mContext.startActivity(intent);
         android.os.Process.killProcess(android.os.Process.myPid());
   // 退出程序
         //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) {
    String versionName = pi.versionName == null ? "null" : pi.versionName;
    String versionCode = pi.versionCode + "";
    infos.put("BUILD_TIME","20150212");
    infos.put("maxMemory", Runtime.getRuntime().maxMemory()/1024/1024+" MB");
    infos.put("versionName", versionName);
    infos.put("versionCode", versionCode);
    infos.put("mounts", readFileByLines("/proc/mounts"));
    infos.put("getDisplayMetrics", ctx.getResources().getDisplayMetrics().widthPixels + "*"
      + ctx.getResources().getDisplayMetrics().heightPixels);

   }
  } 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);
   }
  }
 }

 public  String readFileByLines(String fileName) {
  StringBuilder sb = new StringBuilder();
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
             sb.append(tempString+"\r\n");
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return sb.toString();
    }


 /**
  * 保存错误信息到文件中
  * 
  * @param ex
  * @return 返回文件名称,便于将文件传送到服务器
  */
 private String saveCrashInfo2File(Throwable ex) {
  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());
      final String fileName = "crash-" + time + "-" + timestamp + ".log";
      final String path = getStorageDirectory();
      System.out.println(path);
      File dir = new File(path);
      if (!dir.exists()) {
      dir.mkdirs();
    }
    File file = new File(path + File.separator + fileName);
    file.createNewFile();
    FileOutputStream fos = new FileOutputStream(path + fileName);
    fos.write(sb.toString().getBytes());
    fos.flush();
    fos.close();

    //上传到服务器
//   new Thread(new Runnable() {
//    
//    @Override
//    public void run() {
//     try {
//      List<BasicNameValuePair> postData=new ArrayList<BasicNameValuePair>();
//      String prefix = "";
//      if (sb.toString().contains("java.lang.NullPointerException")) {
//       prefix = "NP-";
//      }else if (sb.toString().contains("java.lang.OutOfMemoryError")) {
//       prefix = "OOM-";
//      }
//      if (LogUtil.isDebug) {
//       prefix = "Debug-";
//      }
//      String nameStr= prefix + android.os.Build.MANUFACTURER+"-"+android.os.Build.MODEL+"-"+android.os.Build.VERSION.SDK+".txt";
//      postData.add(new BasicNameValuePair("name", nameStr));
//      postData.add(new BasicNameValuePair("data", sb.toString()));

//      LogUtil.d("upload",Post("上传的奔溃日志的url地址", postData, 10, 10));
//     } catch (Exception e) {
//      e.printStackTrace();
//      LogUtil.d("upload", "Exception", e);
//     }
//     
//    }
//   }).start();
   return fileName;
  } catch (Exception e) {
   Log.e("upload", "an error occured while writing file...", e);
  }
  return null;
 }



 /**
  * 
  * @param URL  上传地址
  * @param params  参数
  * @param ConnectionTimeout  连接超时时间
  * @param SoTimeout
  * @return
  */

 public  String Post(String URL, List<BasicNameValuePair> params, int ConnectionTimeout, int SoTimeout) {  
        HttpPost httpPost = new HttpPost(URL); 
        String returnString = null;  
        HttpParams httpParameters = new BasicHttpParams();  
        try {
         if(params!=null){
          UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(  
                    params, "utf-8");  
             httpPost.setEntity(urlEncodedFormEntity);
             for(BasicNameValuePair param : params){
//              Log.e(">>>"+ param.getName() , param.getValue());
             }
         }
            HttpConnectionParams.setConnectionTimeout(httpParameters, 1000*ConnectionTimeout);  
            HttpConnectionParams.setSoTimeout(httpParameters, 1000*SoTimeout);
            HttpClient httpClient = new DefaultHttpClient(httpParameters);  
            HttpResponse httpResponse = httpClient.execute(httpPost);  
            HttpEntity httpEntity = httpResponse.getEntity();  
            InputStream inputStream = httpEntity.getContent();  
            BufferedInputStream bufferedInputStream = new BufferedInputStream(  
                    inputStream);  
            ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);  
            int current = 0;  
            while ((current = bufferedInputStream.read()) != -1) {  
                byteArrayBuffer.append(current);  
            }  
            returnString = EncodingUtils.getString(byteArrayBuffer  
                    .toByteArray(), "utf-8");  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        } catch (ClientProtocolException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return returnString;  
    } 


  /**
 * 
 * @类说明  日志输出类
 *  配合异常处理类使用
 */
public class LogUtil {
 /**
  * isDebug = true 为输出log 奔溃异常直接打印
  * 
  * isDebug = false 为关闭log 异常直接上传服务器
  */
 public static final boolean isDebug = true;

 public static void d(String msg) {
  if (isDebug)
   d("nalan", msg);
 }
 public static void d(String TAG, String msg) {
  if (isDebug)
   Log.d(TAG, msg);
 }
 public static void i(String msg) {
  if (isDebug)
   i("nalan", msg);
 }
 public static void i(String TAG, String msg) {
  if (isDebug)
   Log.i(TAG, msg);
 }
 public static void v(String TAG, String msg) {
  if (isDebug)
   Log.v(TAG, msg);
 }
 public static void e(String msg) {
  if (isDebug)
   e("nalan", msg);
 }
 public static void e(String TAG, String msg) {
  if (isDebug)
   Log.e(TAG, msg);
 }
}  

//在 Application 中调用
public class YouApplication extends Application {    
     @Override
     public void onCreate() {
      super.onCreate();

          if (!LogUtil.isDebug) {
               CrashHandler crashHandler = CrashHandler.getInstance();
               crashHandler.init(getApplicationContext());
         }  
       }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值