Android之异常信息拦截

不论是个人还是团队开发,软件或多或少都会出现BUG,当出现BUG,开发人员就会想知道异常信息是什么,所以为了方便维护,Android开发都会通过继承Thread类内部的UncaughtExceptionHandler接口来记录保存异常信息,下面来具体分析该功能所用到的方法

首先要定义一个类来继承UncaughtExceptionHandler接口,并且重写uncaughtException方法,然后进行初始化,获取到系统的异常终止处理器。

UncaughtExceptionHandler接口代码

 public interface UncaughtExceptionHandler {
   
        void uncaughtException(Thread t, Throwable e);
    }


此接口意义就是当线程出现异常终止时,默认是会把异常信息抛出给JAVA虚拟机进行处理。

getDefaultUncaughtExceptionHandler和setDefaultUncaughtExceptionHandler代码

public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
        return defaultUncaughtExceptionHandler;
    }
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
         defaultUncaughtExceptionHandler = eh;
     }

getDefaultUncaughtExceptionHandler方法是返回当线程突然终止时调用的默认处理程序,但是未捕获异常就会返回值为空。

setDefaultUncaughtExceptionHandler方法是设置线程突然终止时调用的默认处理程序,也就是自己想代替默认处理机制时,所做的操作。

当定义了setDefaultUncaughtExceptionHandler,就会回调UncaughtExceptionHandler的uncaughtException方法,来执行信息记录或者上传

下面就举个保存异常信息到TXT文档中列子

完整代码:

CrashHandler类

public class CrashHandler implements UncaughtExceptionHandler {
    private Thread.UncaughtExceptionHandler mhandler;
    private static CrashHandler CRASHINSTANCE;
    private Context mcontext;
    //用于存储设备的相关信息
    private Map<String, String> item = new HashMap<>();

    /**
     * 实例化实现单列模式
     */
    private CrashHandler() {
    }

    //获取CrashHandler实例,单列模式
    public static synchronized CrashHandler getInstance() {
        if (CRASHINSTANCE == null) {
            CRASHINSTANCE = new CrashHandler();
        }
        return CRASHINSTANCE;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        this.mcontext = context;
        // 获取系统默认的UncaughtException处理器
        mhandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置该CrashHandler为程序的默认处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    /**
     * 收集错误信息的处理
     */
    public boolean handlerException(final Throwable ex) {
        if (ex == null) {
            return false;
        }
        //收集设备信息写入SD卡文件中
        getInfo(ex);
        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mcontext,"程序出现异常,将退出", Toast.LENGTH_LONG).show();
                Looper.loop();
                
            }
        }).start();
        return true;
    }

    /**
     * 收集设备信息
     */
    public void getInfo(Throwable exc) {
        try {
            //APK版本号
            PackageManager pack = mcontext.getPackageManager();
            PackageInfo info = pack.getPackageInfo(mcontext.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (info != null && info.versionName != null) {
                item.put("versionName", info.versionName);
                item.put("versionCode", info.versionCode + "");
            }
            //手机设备品牌和型号
            TelephonyManager phone = (TelephonyManager) mcontext.getSystemService(Context.TELEPHONY_SERVICE);
            if (phone != null) {
                item.put("PhoneName", Build.BOARD);//手机品牌
                item.put("PhoneType", Build.MODEL);//手机型号
            }
            StringBuffer sb = new StringBuffer();
            //先把map里面的值存入sb中
            for (Map.Entry<String, String> entry : item.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                sb.append(key + "=" + value + "\n");
            }
            /*把错误信息存入sb中*/
            Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            exc.printStackTrace(printWriter);
            Throwable cause = exc.getCause();
            while (cause != null) {
                cause.printStackTrace(printWriter);
                cause = cause.getCause();
            }
            printWriter.close();
            String result = writer.toString();
            sb.append(result);
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                File file = new File(Environment.getExternalStorageDirectory() + "/cqq/crash");
                if (!file.exists()) {
                    file.mkdirs();
                }
                File filed = new File(file, "log.txt");
                if (filed.exists()) {
                    filed.delete();
                }
                filed.createNewFile();
                FileOutputStream output = new FileOutputStream(filed);
                output.write(sb.toString().getBytes());
                output.flush();
                output.close();
            }

        } catch (Exception ex) {
        }
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        if (!handlerException(e) && mhandler != null) {
            mhandler.uncaughtException(t, e);
        }else{
              //等候两秒后退出
            try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(0);
       }

    }


 }
}

application类就需要对crash进行监控,需要在onCreate添加如下代码

//截取程序出现错误时的错误信息
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext()); 

文档将会保存在SD卡下cqq/crash下的log.txt,带有设备信息和异常信息。

希望这篇文章可以帮到大家更好的学习!


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值