android UncaughtExceptionHandler全局异常处理
在编写android客户端应用时,总会由于各种各样的原因,导致我们的程序异常退出,这些原因包括:程序的不合理,异常的未捕获,这些通过我们的review都是可以提高的,但是如果是由于android不同的系统版本,不同的配置的机型导致我们的程序异常退出,这是无法避免的,但如何才能减少这个原因导致的程序异常呢,这正是写本篇文章的意图.
在全局异常处理开始前,有两个类是我们必须要知道的,一个是android的Application类,这个类是一个应用程序的全局类,可以将一些所有模块都会用的公共信息都放在这个类中初始化,例如:用户登陆信息,手机信息等,一个应用程序的启动最先启动的就是其对应的Application类的实例,然后再由这个实例去调用要启动的那个Activity,另一个就是全局异常捕获类:Thread.UncaughtExceptionHandler,线程未捕获异常处理器,用来处理未捕获异常。如果程序出现了未捕获异常,默认会弹出系统中强制关闭对话框。我们需要实现此接口,并注册为程序中默认未捕获异常处理。这样当未捕获异常发生时,就可以定制异常处理操作,例如:将异常信息存放到SD卡文件中,将应用程序强制关闭,上传错误的日志文件等.
一般情况下出现这种异常的原因有以下几点:
1.应用的兼容性欠缺,不过这个孔明 没有办法的事件,android手机千差万别,不同的硬件配置,不同的的手机尺寸,不同的系统版本,所以难免会有考虑不周全的地方.
2.编写程序时使用了高版本的API,这样当应用跑到低版本的android系统时自然会有异常发生.
第二种情况是我们在写代码时可以尽量避免的,那就是如果用到了高版本的API,那一定要针对低版本的系统去做处理,这样就可减少这个原因产生的异常.那对于第一种情况怎么办呢,就要用到我们今天的主角,全局异常捕获了.
当APP异常退出时,这部分异常信息是可以通过全局异常处理机制捕获到的,一旦捕获到后,就可以上传到我们的文件服务器中,去做分析,针对性的改进,这就是全局异常处理最主要的作用.
全局异常示例代码:
/********************************************************** * @文件名称:MicCrashHandler.java * @创建时间:2014年10月20日 下午1:10:15 * @文件描述:捕获全局未处理到的异常,上传服务器 * @修改历史:2014年10月20日创建初始版本 **********************************************************/public class MicCrashHandler implements UncaughtExceptionHandler{ public static final String TAG = "MicCrashHandler"; /** * 系统默认的异常捕获类 */ private Thread.UncaughtExceptionHandler mDefaultHandler; /** * 自定义异常处理类 */ private static MicCrashHandler INSTANCE; private Context mContext; /** * 存储异常信息 */ private HashMap infos = new HashMap(); // 存储文件夹路径 private static final String path = Environment.getExternalStorageDirectory() + "/focustech/mic/log/"; private File dirFile; private File file; private static final String fileName = "mic_crash_exception.log"; private MicCrashHandler() { } static { INSTANCE = new MicCrashHandler(); } /** * 单例模式,获取自定义异常处理类 */ public static MicCrashHandler getInstance() { return INSTANCE; } public void init(Context context) { mContext = context; mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } /** * * 自定义异常处理 * @param thread * @param ex */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex) && mDefaultHandler != null) { // 如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { } } /** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. */ private boolean handleException(Throwable ex) { if (ex == null) { return false; } new Thread() { @Override public void run() { Looper.prepare(); ToastUtil.toast(mContext, R.string.crash_exception); Looper.loop(); } }.start(); // 收集设备参数信息 Util.collectDeviceInfo(mContext, infos); // 保存日志文件 saveCrashInfo2File(ex); /** * 以后要加上传功能,需要启动服务去上传应该 */ // uploadExceptionFile(); ActivityManager.getInstance().finishAllActivity(); Process.killProcess(Process.myPid()); System.exit(0); return true; } /** * 保存错误信息到文件中 * @param ex * @return 返回文件名称,便于将文件传送到服务器 */ private void saveCrashInfo2File(Throwable ex) { /** * 组装异常信息 */ String exceptionMsg = assembleExceptionMsg(ex); try { if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { dirFile = new File(path); if (!dirFile.exists()) { dirFile.mkdirs(); } file = new File(path + fileName); RandomAccessFile fos = new RandomAccessFile(file, "rw"); fos.seek(file.length()); fos.write(exceptionMsg.getBytes()); fos.close(); } } catch (Exception e) { e.printStackTrace(); } } /** * 组装异常信息,在这里拼装想要的格式 */ private String assembleExceptionMsg(Throwable ex) { StringBuffer sb = new StringBuffer(); for (Map.Entry 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 + "\r\n"); return sb.toString(); } /** * 发送上传文件请求 */ @SuppressWarnings("unused") private void uploadExceptionFile() { if (!NetworkUtils.isConnectInternet(mContext)) { return; } if (file == null || !file.exists()) { return; } else { RequestCenter.uploadExceptionFile(mContext, listener, file); } } private DisposeDataListener listener = new DisposeDataListener() { @Override public void onSuccess(Object obj) { /** * 发送成功后,还要删除此异常文件,才退出 */ SysManager.exitSystem(mContext); } @Override public void onFailure(Object failedReason) { SysManager.exitSystem(mContext); } };}
更多相关文章
- Android中Activity全局共享方法AppContext
- Android(安卓)Touch事件传递机制解析
- Android音视频处理技术 视频录制
- Android调用系统相机、自定义相机、处理大图片
- Android(安卓)之 Window、WindowManager 与窗口管理
- 让editView、AutoCompleteTextView开始捕获的焦点
- Android菜鸟的成长笔记(11)——Android中的事件处理
- Android中Activity全局共享方法AppContext
- Android日志打印与处理 UncaughtExceptionHandler 提交服务器