博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android捕获全局异常
阅读量:4180 次
发布时间:2019-05-26

本文共 4462 字,大约阅读时间需要 14 分钟。

        Android捕获全局异常其实利用的就是Thread捕获异常,Android中的UI线程其实就是一个普通的Thread,不过它里面维护了一个Handler,这个Handler对Android的整个应用的运行起到了很大的作用,可以这么说Android应用的运行就是基于Handler。

        接下来让我们来看看Thread类是如何捕获异常的,Thread中有一个接口,如下:

 

 
public interface UncaughtExceptionHandler {    /**     * Method invoked when the given thread terminates due to the     * given uncaught exception.     * 

Any exception thrown by this method will be ignored by the * Java Virtual Machine. * @param t the thread * @param e the exception */ void uncaughtException(Thread t, Throwable e);}public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { defaultUncaughtExceptionHandler = eh;}public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ return defaultUncaughtExceptionHandler;}

这个接口的作用就是当有异常发生在这个线程中时会调用到这个方法,这样我们就可以实现这个接口然后注入进去就可以了。

        这里我对这个做了一个简易的封装,功能就是捕获线程异常然后打印到sdcard,当然也可以把捕获到的异常发送到服务器:

 

public class CrashHandler implements Thread.UncaughtExceptionHandler {    private static final String TAG = "CrashHandler";    private final Thread.UncaughtExceptionHandler defaultHandler;    private static final String CRASH_DIR = "_crash.log";    private CrashHandler() {        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();        Thread.setDefaultUncaughtExceptionHandler(this);    }    private static class InstanceHold{        public static CrashHandler instance = new CrashHandler();    }    public static CrashHandler getInstance(){        return InstanceHold.instance;    }    @Override    public void uncaughtException(Thread t, Throwable ex) {        if (!handleExceptionMessage(ex) && defaultHandler != null){            defaultHandler.uncaughtException(t,ex);        }else {            try{                Thread.sleep(3000);            }catch (InterruptedException e){                e.printStackTrace();            }            Process.killProcess(Process.myPid());            System.exit(1);        }    }    public boolean handleExceptionMessage(Throwable e){        StringWriter sw = new StringWriter();        sw.append("这是自定义抛异常\n");        PrintWriter pw = new PrintWriter(sw);        e.printStackTrace(pw);        File file;        try {            file = new File(getCrashDir());            FileWriter fw = new FileWriter(file);            fw.write(sw.toString());            fw.close();        } catch (IOException e1) {            e1.printStackTrace();            return false;        }        Log.e(TAG, sw.toString());        pw.close();        return true;    }    public String getCrashDir(){        StringBuffer buffer = new StringBuffer();        buffer.append(Environment.getExternalStorageDirectory()+File.separator).append(BuildConfig.APPLICATION_ID).append(getTime()).append(CRASH_DIR);        return buffer.toString();    }    public String getTime(){        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");        String time = format.format(new Date());        return time;    }}

当你想要在哪个线程中监听异常时,直接在该线程调用

CrashHandler.getInstance();

这样,该线程有异常发生时就会打印到sdcard,如果想要监听UI线程,直接在Application的onCreate()中调用该方法即可。

        对于日志的查看,我个人比较喜欢在Android studio的Terminal中查看,比较的方便,Terminal中查看首先你得做以下几步:

        1、首先在环境变量中配置adb,不会的可自行百度;

        2、在Terminal中输入adb shell;

        3、使用cd命令跳转到对应的目录先,我这里用到的是cd sdcard跳转到sdcard目录下,如果手机没有root权限,其他目录是cd不了的。

        4、接下来就是找到我们打印的文件,可以使用 ls -l *_crash.log这个命令,就会列出当前目录下以_crash.log结尾的得所有文件,我保存的文件就是以_crash.log结尾;

 root@generic_x86:/sdcard # ls -l *.log

-rwxrwx--- root   sdcard_r  725 2018-04-10 03:12 com.example.ubt.myapplication2018-04-10_crash.log

        5、找到文件后就剩打开文件了,使用cat filename即可查看,如下:

root@generic_x86:/sdcard # cat  com.example.ubt.myapplication2018-04-10_crash.log

        6、如果出现答应中文是乱码的情况,说明编码方式不对,退出shell的模式,使用chcp 65001换成utf-8编码,默认情况下是gbk编码,如果想改回gbk编码,可以使用chcp 936.

使用cat命令后输出的信息如下:

java.lang.NullPointerException

        at com.example.ubt.myapplication.TestStudioActivity$1.onClick(TestStudioActivity.java:53)
        at android.view.View.performClick(View.java:4780)
        at android.view.View$PerformClick.run(View.java:19866)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)

        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

使用这样的方式查看日志就不必从sdcard中拷贝出来,而且看起来也很舒服。

转载地址:http://fzhai.baihongyu.com/

你可能感兴趣的文章
在可执行jar中动态载入第三方jar(转贴)
查看>>
考虑体积重量的01背包问题—基于遗传算法
查看>>
K-means 聚类算法
查看>>
带约束的K-means聚类算法
查看>>
约束优化方法
查看>>
VRPTW建模与求解—基于粒子群算法
查看>>
数据结构与算法(1):大O表示法
查看>>
Java学习知识树
查看>>
文科生,你为啥学编程?
查看>>
使用Eclipse时出现Unhandled event loop exception错误的有效解决办法
查看>>
JAVA之路:第一章 JAVA入门初体验
查看>>
菜鸟文科生的java之路:运算符
查看>>
菜鸟文科生的java之路:变量和常量
查看>>
菜鸟文科生的java之路:流程控制语句
查看>>
北海糖:Java初阶练习题
查看>>
不知道什么是数组?看这里就好了
查看>>
文科生北海唐的Java之路:方法(慕课)
查看>>
自学Java的轨迹线路
查看>>
如何更好的隐藏你自己,让我们谈谈什么是封装?
查看>>
文科生北海糖的:Java之路——继承
查看>>