Android崩溃异常捕获方法

Android崩溃异常捕获方法,第1张

概述开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。

开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。
那么今天主要讲一下如何去捕捉系统出现的Unchecked异常。何为Unchecked异常呢,换句话说就是指非受检异常,它不能用try-catch来显示捕捉。

我们先从Exception讲起。Exception分为两类:一种是CheckedException,一种是UncheckedException。这两种Exception的区别主要是CheckedException需要用try...catch...显示的捕获,而UncheckedException不需要捕获。通常UncheckedException又叫做RuntimeException。《effective java》指出:对于可恢复的条件使用被检查的异常(CheckedException),对于程序错误(言外之意不可恢复,大错已经酿成)使用运行时异常(RuntimeException)。我们常见的RuntimeExcepiton有IllegalArgumentException、IllegalStateException、NullPointerException、indexoutofboundsexception等等。对于那些CheckedException就不胜枚举了,我们在编写程序过程中try...catch...捕捉的异常都是CheckedException。io包中的IOException及其子类,这些都是CheckedException。

一、使用UncaughtExceptionHandler来捕获unchecked异常

UncaughtException处理类,当程序发生Uncaught异常的时候,由该类来接管程序,并记录发送错误报告。
直接上代码吧

import java.io.file;import java.io.fileOutputStream;import java.io.PrintWriter;import java.io.StringWriter;import java.io.Writer;import java.lang.Thread.UncaughtExceptionHandler;import java.lang.reflect.FIEld;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Locale;import java.util.Map;import java.util.Map.Entry;import java.util.regex.Matcher;import java.util.regex.Pattern;import androID.annotation.Suppresslint;import androID.content.Context;import androID.content.pm.PackageInfo;import androID.content.pm.PackageManager;import androID.content.pm.PackageManager.nameNotFoundException;import androID.os.Build;import androID.os.Environment;import androID.os.Looper;import androID.util.Log;import androID.Widget.Toast;/*** UncaughtException处理类,有该类来接管程序,并记录发送错误报告.* * @author user* */@Suppresslint("SdCardpath")public class CrashHandler implements UncaughtExceptionHandler {public static final String TAG = "TEST";// CrashHandler 实例private static CrashHandler INSTANCE = new CrashHandler();// 程序的 Context 对象private Context mContext;// 系统默认的 UncaughtException 处理类private Thread.UncaughtExceptionHandler mDefaultHandler;// 用来存储设备信息和异常信息private Map<String,String> infos = new HashMap<String,String>();// 用来显示Toast中的信息private static String error = "程序错误,额,不对,我应该说,服务器正在维护中,请稍后再试";private static final Map<String,String> regexMap = new HashMap<String,String>();// 用于格式化日期,作为日志文件名的一部分private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss",Locale.CHINA);/** 保证只有一个 CrashHandler 实例 */private CrashHandler() {//}/** 获取 CrashHandler 实例,单例模式 */public static CrashHandler getInstance() {initMap();return INSTANCE;}/*** 初始化* * @param context*/public voID init(Context context) {mContext = context;// 获取系统默认的 UncaughtException 处理器mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 设置该 CrashHandler 为程序的默认处理器Thread.setDefaultUncaughtExceptionHandler(this);Log.d("TEST","Crash:init");}/*** 当 UncaughtException 发生时会转入该函数来处理*/@OverrIDepublic voID uncaughtException(Thread thread,Throwable ex) {if (!handleException(ex) && mDefaultHandler != null) {// 如果用户没有处理则让系统默认的异常处理器来处理mDefaultHandler.uncaughtException(thread,ex);Log.d("TEST","defalut");} else {try {Thread.sleep();} catch (InterruptedException e) {Log.e(TAG,"error : ",e);}// 退出程序androID.os.Process.killProcess(androID.os.Process.myPID());// mDefaultHandler.uncaughtException(thread,ex);System.exit();}}/*** 自定义错误处理,收集错误信息,发送错误报告等 *** 作均在此完成* * @param ex* @return true:如果处理了该异常信息;否则返回 false*/private boolean handleException(Throwable ex) {if (ex == null) {return false;}// 收集设备参数信息// collectDeviceInfo(mContext);// 保存日志文件saveCrashInfofile(ex);// 使用 Toast 来显示异常信息new Thread() {@OverrIDepublic voID run() {Looper.prepare();Toast.makeText(mContext,error,Toast.LENGTH_LONG).show();Looper.loop();}}.start();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("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 返回文件名称,便于将文件传送到服务器*/private String saveCrashInfofile(Throwable ex) {StringBuffer sb = getTraceInfo(ex);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 = Environment.getExternalStorageDirectory()+ "/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);}return null;}/*** 整理异常信息* @param e* @return*/public static StringBuffer getTraceInfo(Throwable e) {StringBuffer sb = new StringBuffer();Throwable ex = e.getCause() == null ? e : e.getCause();StackTraceElement[] stacks = ex.getStackTrace();for (int i = ; i < stacks.length; i++) {if (i == ) {setError(ex.toString());}sb.append("class: ").append(stacks[i].getClassname()).append("; method: ").append(stacks[i].getmethodname()).append("; line: ").append(stacks[i].getlineNumber()).append("; Exception: ").append(ex.toString() + "\n");}Log.d(TAG,sb.toString());return sb;}/*** 设置错误的提示语* @param e*/public static voID setError(String e) {Pattern pattern;Matcher matcher;for (Entry<String,String> m : regexMap.entrySet()) {Log.d(TAG,e+"key:" + m.getKey() + "; value:" + m.getValue());pattern = Pattern.compile(m.getKey());matcher = pattern.matcher(e);if(matcher.matches()){error = m.getValue();break;}}}/*** 初始化错误的提示语*/private static voID initMap() {// java.lang.NullPointerException// java.lang.classNotFoundException// java.lang.ArithmeticException// java.lang.Arrayindexoutofboundsexception// java.lang.IllegalArgumentException// java.lang.illegalaccessexception// SecturityException// NumberFormatException// OutOfMemoryError // StackOverflowError // RuntimeException regexMap.put(".*NullPointerException.*","嘿,无中生有~Boom!");regexMap.put(".*ClassNotFoundException.*","你确定你能找得到它?");regexMap.put(".*ArithmeticException.*","我猜你的数学是体育老师教的,对吧?");regexMap.put(".*Arrayindexoutofboundsexception.*","恩,无下限=无节 *** ,请不要跟我搭话");regexMap.put(".*IllegalArgumentException.*","你的出生就是一场错误。");regexMap.put(".*illegalaccessexception.*","很遗憾,你的xyk账号被冻结了,无权支付");regexMap.put(".*SecturityException.*","死神马上降临");regexMap.put(".*NumberFormatException.*","想要改变一下自己形象?去泰国吧,包你满意");regexMap.put(".*OutOfMemoryError.*","或许你该减减肥了");regexMap.put(".*StackOverflowError.*","啊,啊,憋不住了!");regexMap.put(".*RuntimeException.*","你的人生走错了方向,重来吧");}}

二、建立一个Application来全局监控

import androID.app.Application;public class CrashApplication extends Application {@OverrIDepublic voID onCreate() {super.onCreate();CrashHandler crashHandler = CrashHandler.getInstance();crashHandler.init(getApplicationContext());}} 

最后在配置文件中加入注册信息

<application androID:name=".CrashApplication" ... /> 

和权限

<!--uses-permission androID:name="androID.permission.ACCESS_NETWORK_STATE" /--><uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" /> 

提交错误日志到网络服务器这一块还没有添加。如果添加了这一块功能,就能够实时的得要用户使用时的错误日志,能够及时反馈不同机型不同时候发生的错误,能对我们开发者的后期维护带来极大的方便。

有关AndroID崩溃异常捕获方法小编就给大家介绍这么多,希望对大家有所帮助!

总结

以上是内存溢出为你收集整理的Android崩溃异常捕获方法全部内容,希望文章能够帮你解决Android崩溃异常捕获方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1149514.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存