importjava.io.File; | |
importjava.io.FileOutputStream; | |
importjava.io.PrintWriter; | |
importjava.io.StringWriter; | |
importjava.io.Writer; | |
importjava.lang.Thread.UncaughtExceptionHandler; | |
importjava.lang.reflect.Field; | |
importjava.text.DateFormat; | |
importjava.text.SimpleDateFormat; | |
importjava.util.Date; | |
importjava.util.HashMap; | |
importjava.util.Map; | |
importandroid.app.AlarmManager; | |
importandroid.app.PendingIntent; | |
importandroid.content.Context; | |
importandroid.content.Intent; | |
importandroid.content.pm.PackageInfo; | |
importandroid.content.pm.PackageManager; | |
importandroid.content.pm.PackageManager.NameNotFoundException; | |
importandroid.os.Build; | |
importandroid.os.Environment; | |
importandroid.os.Looper; | |
importandroid.os.Process; | |
importandroid.util.Log; | |
importandroid.widget.Toast; | |
importcom.bwei.xme.MainActivity; | |
import staticandroid.content.Intent.FLAG_ACTIVITY_NEW_TASK; | |
/** | |
* UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. | |
* | |
* @author user | |
* | |
*/ | |
publicclass CrashHandler implements UncaughtExceptionHandler { | |
publicstatic final String TAG = "CrashHandler"; | |
//系统默认的UncaughtException处理类 | |
privateThread.UncaughtExceptionHandler mDefaultHandler; | |
//CrashHandler实例 | |
privatestatic CrashHandler INSTANCE = new CrashHandler(); | |
//程序的Context对象 | |
privateContext mContext; | |
//用来存储设备信息和异常信息 | |
privateMap<String, String> infos= new HashMap<String,String>(); | |
//用于格式化日期,作为日志文件名的一部分 | |
privateDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); | |
/** 保证只有一个CrashHandler实例*/ | |
privateCrashHandler() { | |
} | |
/** 获取CrashHandler实例 ,单例模式*/ | |
publicstatic CrashHandler getInstance() { | |
returnINSTANCE; | |
} | |
/** | |
* 初始化 | |
* | |
* @param context | |
*/ | |
publicvoid init(Contextcontext) { | |
mContext = context; | |
//获取系统默认的UncaughtException处理器 | |
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); | |
//设置该CrashHandler为程序的默认处理器 | |
Thread.setDefaultUncaughtExceptionHandler(this); | |
} | |
/** | |
* 当UncaughtException发生时会转入该函数来处理 | |
*/ | |
@Override | |
publicvoid uncaughtException(Threadthread, Throwable ex) { | |
if (!handleException(ex)&& mDefaultHandler != null) { | |
//如果用户没有处理则让系统默认的异常处理器来处理 | |
mDefaultHandler.uncaughtException(thread, ex); | |
} else { | |
//退出程序 | |
//第一种方法 | |
// | |
// Intent intent = new Intent(mContext, ReportActivity.class); | |
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
// mContext.startActivity(intent); | |
// | |
// Process.killProcess(Process.myPid()); | |
//第二种方法 | |
// Intent intent = new Intent(mContext, MainActivity.class); | |
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
// mContext.startActivity(intent); | |
// android.os.Process.killProcess(android.os.Process.myPid()); | |
} | |
} | |
/** | |
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. | |
* | |
* @param ex | |
* @return true:如果处理了该异常信息;否则返回false. | |
*/ | |
privateboolean handleException(Throwableex) { | |
if (ex== null) { | |
returnfalse; | |
} | |
// 使用Toast来显示异常信息 | |
// new Thread() { | |
// @Override | |
// public void run() { | |
// Looper.prepare(); | |
// Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show(); | |
// Looper.loop(); | |
// } | |
// }.start(); | |
//收集设备参数信息 | |
collectDeviceInfo(mContext); | |
//保存日志文件 | |
saveCrashInfo2File(ex); | |
returntrue; | |
} | |
/** | |
* 收集设备参数信息 | |
* @param ctx | |
*/ | |
publicvoid collectDeviceInfo(Contextctx) { | |
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("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 返回文件名称,便于将文件传送到服务器 | |
*/ | |
privateString saveCrashInfo2File(Throwableex) { | |
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"); | |
} | |
sb.append(ex.getMessage()); | |
System.out.println("sb =" + sb.toString()); | |
// | |
// 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"; | |
// if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { | |
// String path = "/sdcard/crash/"; | |
// File dir = new File(path); | |
// if (!dir.exists()) { | |
// dir.mkdirs(); | |
// } | |
// FileOutputStream fos = new FileOutputStream(path + fileName); | |
// fos.write(sb.toString().getBytes()); | |
// fos.close(); | |
// } | |
// return fileName; | |
// } catch (Exception e) { | |
// Log.e(TAG, "an error occured while writing file...", e); | |
// } | |
returnnull; | |
} | |
} 在application类的oncreate里
CrashHandler.getInstance(). init(this);
|
异常捕获器
最新推荐文章于 2024-07-31 21:24:25 发布