Android 全局 异常捕捉
1 在application中
1 主要类//本地异常记录
public class CrashHandlerUtils implements UncaughtExceptionHandler {
private static final String TAG = “CrashHandler”;
private UncaughtExceptionHandler mDefaultHandler;// 系统默认的UncaughtException处理类
private static CrashHandlerUtils INSTANCE = new CrashHandlerUtils();// CrashHandler实例
private Context mContext;// 程序的Context对象
private Map<String, String> info = new HashMap<String, String>();// 用来存储设备信息和异常信息
private SimpleDateFormat format = new SimpleDateFormat(
“yyyy-MM-dd-HH-mm-ss”);// 用于格式化日期,作为日志文件名的一部分
public static final int MSG_EMAIL = 0;
public static final int MSG_FILE = 1;
private int type;
private MyApplication myapplication;
/**
* 是否自动重启
*/
private boolean reStart = false;
/**
* 保证只有一个CrashHandler实例
*/
private CrashHandlerUtils() {
}
/**
* 获取CrashHandler实例 ,单例模式
*/
public static CrashHandlerUtils getInstance() {
return INSTANCE;
}
public boolean isReStart() {
return reStart;
}
public void setReStart(boolean reStart) {
this.reStart = reStart;
}
/**
* 设置该CrashHandler为程序的默认处理器
*/
public void init(Context context, int type) {
this.type = type;
mContext = context;
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器
Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器
}
/**
* 重写@:当UncaughtException发生时会转入该重写的方法来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果自定义的没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
// try {
// Thread.sleep(3000);// 如果处理了,让程序继续运行3秒再退出,保证文件保存并上传到服务器
// restartApp();
// } catch (Exception e) {
// restartApp();
// e.printStackTrace();
// }
}
}
public void restartApp() {
AlarmManager mgr = (AlarmManager) mContext.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext.getApplicationContext(), MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("crash", true);
PendingIntent restartIntent = PendingIntent.getActivity(mContext.getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 8000, restartIntent); //秒钟后重启应用
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
System.gc();
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex 异常信息
* @return true 如果处理了该异常信息;否则返回false.
*/
public boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
// new Thread() {
// public void run() {
// Looper.prepare();
// Toast.makeText(mContext, “程序即将重启”, Toast.LENGTH_SHORT).show();
// Looper.loop();
// }
// }.start();
// 收集设备参数信息
collectDeviceInfo(mContext, info);
// 保存日志文件
saveCrashInfo2File(ex);
return true;
}
/**
* 收集设备参数信息
*
* @param context
*/
public static void collectDeviceInfo(Context context,
Map<String, String> info) {
try {
PackageManager pm = context.getPackageManager();// 获得包管理器
PackageInfo pi = pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity
if (pi != null) {
String versionName = pi.versionName == null ? "null"
: pi.versionName;
String versionCode = pi.versionCode + "";
info.put("versionName", versionName);
info.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
Field[] fields = Build.class.getDeclaredFields();// 反射机制
for (Field field : fields) {
try {
field.setAccessible(true);
info.put(field.getName(), field.get("").toString());
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 把錯誤信息保存本地。
*
* @param ex
* @return
*/
private String saveCrashInfo2File(Throwable ex) {
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : info.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
// 循环着把所有的异常信息写入writer中
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();// 记得关闭
String result = writer.toString();
UploadException(result,sb.toString(),ex.toString());
sb.append(result);
LUtils.e("System.out", "错误信息:" + sb.toString());
// 保存文件
long timetamp = System.currentTimeMillis();
String time = format.format(new Date());
String fileName = "crash-" + time + "-" + timetamp + ".log";
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
File dir = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator + "ErrorInfo");
LUtils.i("CrashHandler", dir.toString());
if (!dir.exists()) {
dir.mkdir();
} else {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
if (files.length > 300) {
List<File> list = new ArrayList<>();
try {
for (int x = 0, len = files.length; x < len; x++) {
File file = files[x];
list.add(file);
}
Collections.sort(list, new Comparator<File>() {
@Override
public int compare(File file, File file1) {
return file.getName().compareTo(file1.getName());
}
@Override
public boolean equals(Object o) {
return false;
}
});
for (int x = 0, len = list.size(); x < len && x < len - 300; x++) {
File file = list.get(x);
file.delete();
}
// String atr3 = “暗示法撒地方”;
} catch (NumberFormatException e) {
LUtils.e(TAG, "saveCrashInfo2File: "+ e);
}
}
}
}
}
FileOutputStream fos = new FileOutputStream(new File(dir,
fileName));
fos.write(sb.toString().getBytes());
fos.close();
return fileName;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private void UploadException(String stack,String env, String title) {
UmKernel.getInstance().runCachedThread(new Runnable() {
@Override
public void run() {
ExceptionBean exceptionBean= new ExceptionBean();
exceptionBean.setTitle(title);
exceptionBean.setStack(stack);
exceptionBean.setEnv(env);
exceptionBean.setPlatform("android");
exceptionBean.setRemark("fwf");
exceptionBean.setClient(SystemToolUtils.getLocalIpDisplayAddress());
Call<ExceptionBean> exceptionBeanCall =
HttpHelper.getCommonApiUrl().uploadException(exceptionBean);
exceptionBeanCall.enqueue(new Callback<ExceptionBean>() {
@Override
public void onResponse(Call<ExceptionBean> call, Response<ExceptionBean> response) {
if (response != null) {
}
}
@Override
public void onFailure(Call<ExceptionBean> call, Throwable t) {
}
});
}
});
}
}