全局异常处理
来源:互联网 发布:淘宝新店铺如何引流 编辑:程序博客网 时间:2024/05/21 19:03
在项目中,如果有异常未捕获,运行时触发异常,则会将异常抛出,给用户一个不好的体验。
虽然现在系统厂商都对未捕获异常进行了处理,基本不会发生弹出异常,崩溃退出应用的场景,但是我们在项目中一般还是会进行一个全局异常处理,可以自己定义或者使用第三方统计,如有盟统计,腾讯bugly等。
异常定义及分类
异常是指在程序运行过程中所出现的错误,这些错误会干扰到指令的正常执行,从而导致程序异常退出。
对java语言来说,所有异常都继承自Throwable
Error异常是我们无法处理的异常,属于系统异常。
Exception异常是由于我们代码编写失误造成的,可以通过修改代码进行控制。我们所处理的异常都属于此类异常。
异常根据触发时机不同又可分为两种:
编译时异常
如ClassNotFoundException/CanNotFoundId layout未找到id
运行时异常
如数组越界/类型转换异常
对异常的全局处理
/** * Interface for handlers invoked when a <tt>Thread</tt> abruptly * terminates due to an uncaught exception. * 当一个线程因为未捕获异常突然终止时调用*/public interface UncaughtExceptionHandler { /** *未捕获异常处理 */ void uncaughtException(Thread t, Throwable e);}
所以我们只需要实现UncaughtExceptionHandler中uncaughtException方法即可。
public class CrashHandler implements Thread.UncaughtExceptionHandler { private static CrashHandler instance; private Context mcontext; private Thread.UncaughtExceptionHandler mDefualtHandller; private Map<String, String> eMaps = new ArrayMap<>(); private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private boolean isPrintLog; private CrashHandler() { } public static CrashHandler getInstance() { if (instance == null) { synchronized (CrashHandler.class) { if (instance == null) { instance = new CrashHandler(); } } } return instance; } /** * 初始化 * @param context * @param isPrintLog 是否输出错误信息 */ public void init(Context context, boolean isPrintLog) { mcontext = context; this.isPrintLog = isPrintLog; mDefualtHandller = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当触发未捕获异常时,系统将调用此方法 * @param t * @param e */ @Override public void uncaughtException(Thread t, Throwable e) { if (!handleException(e)) { if (mDefualtHandller != null) mDefualtHandller.uncaughtException(t, e); } else { try { Thread.sleep(1000); } catch (InterruptedException e1) { e1.printStackTrace(); } Process.killProcess(Process.myPid()); System.exit(1); } } /** * 是否手动处理未捕获异常 * * @param e * @return */ private boolean handleException(Throwable e) { if (e == null) return false; showExceptionMsg(e); collectExceptionInfo(); saveExceptionInfo(e); return true; } /** * 收集异常信息 */ private void collectExceptionInfo() { PackageManager pm = mcontext.getPackageManager(); try { PackageInfo packageInfo = pm.getPackageInfo(mcontext.getPackageName(), PackageManager.GET_ACTIVITIES); if (packageInfo != null) { eMaps.put("versionName", packageInfo.versionName); eMaps.put("versionCode", String.valueOf(packageInfo.versionCode)); } saveDeviceInfo(); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } /** * 保存设备信息 */ private void saveDeviceInfo() { Field[] fields = Build.class.getFields(); if (fields != null && fields.length > 0) for (Field field : fields) { field.setAccessible(true); try { eMaps.put(field.getName(), field.get(null).toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } } } /** * 保存异常信息到sd卡 */ private void saveExceptionInfo(Throwable e) { StringBuffer stringBuffer = new StringBuffer(); for (Map.Entry<String, String> entry : eMaps.entrySet()) { stringBuffer.append(entry.getKey() + "===" + entry.getValue() + "\n\r"); } Writer write = new StringWriter(); PrintWriter printer = new PrintWriter(write); e.printStackTrace(printer); Throwable cause = e.getCause(); while (cause != null) { cause.printStackTrace(printer); e.getCause(); } printer.close(); stringBuffer.append(write.toString()); long time = System.currentTimeMillis(); String date = dateFormat.format(new Date()); String fileName = "crash-" + date + "-" + time + ".log"; if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { String filePath = "/sdcard/" + mcontext.getPackageName() + "-crash/"; File file = new File(filePath); if (!file.exists()) file.mkdirs(); FileOutputStream fos = null; try { fos = new FileOutputStream(file + fileName); fos.write(stringBuffer.toString().getBytes()); } catch (FileNotFoundException e1) { e1.printStackTrace(); } catch (IOException e1) { e1.printStackTrace(); } finally { try { fos.close(); } catch (IOException e1) { } } } //TODO 将错误信息上次到服务器 } /** * 提示异常信息 */ private void showExceptionMsg(Throwable e) { if (!isPrintLog) return; if (Looper.getMainLooper() == Looper.myLooper()) showToast(e, true); else showToast(e, false); } private void showToast(Throwable e, boolean isMainThread) { if (isMainThread) Toast.makeText(mcontext, "未捕获异常:" + e.getMessage(), Toast.LENGTH_LONG).show(); else { Looper.prepare(); Toast.makeText(mcontext, "未捕获异常:" + e.getMessage(), Toast.LENGTH_LONG).show(); Looper.loop(); } }}
然后在Application中初始化即可。
public class App extends Application { CrashHandler crashHandler; @Override public void onCreate() { super.onCreate(); crashHandler=CrashHandler.getInstance(); crashHandler.init(this,BuildConfig.ISDEBUG); }}
其中BuildConfig.ISDEBUG可以通过在build.gradle中配置
debug{ buildConfigField('boolean' , 'ISDEBUG', 'true') }release { buildConfigField('boolean' , 'ISDEBUG', 'false') minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }
如果是字符串则需要 buildConfigField(‘String’ , ‘aaaa’, ‘\”fadfasfa\”’)
使用第三方统计
使用有盟统计或者腾讯bugly,按照文档设置完成之后,可以在后台看到异常报表
阅读全文
0 0
- 全局异常捕获处理
- 全局异常处理UncaughtExceptionHandler
- Android 全局异常处理
- android处理全局异常
- winfom全局异常处理
- Android 全局异常处理
- Android全局处理异常
- Android 全局异常处理
- Android 全局异常处理
- Android 全局异常处理
- Android 全局异常处理
- Android 全局异常处理
- springMVC 全局异常处理
- 项目全局异常处理
- springMVC全局异常处理
- 全局异常处理
- SpringMVC全局异常处理
- Android 全局异常处理
- Codeforces 337D 树形dp + 小技巧
- 快速幂1006
- Ubuntu 16.04 IP分享服务器搭建
- 本人精心收集的近80个国内最好的嵌入式技术相关网站和论坛和博客
- Problem 10 Summation of primes
- 全局异常处理
- 海康摄像头
- android webview加载html图片自适应手机屏幕大小&点击查看大图
- Nginx 配置文件 nginx.conf 详解
- War Chess HDU
- Spring Cloud学习笔记之高可用部署
- UVa 11313
- JqGrid选中行、取消选中行、获得选中行数据 -yellowcong
- centos6 redis 安装(yum和源码安装)完整步骤