Android 获取应用Crash信息的方法

Android应用不可避免的都会发生crash,即程序崩溃

可能是系统或程序有bug等内部原因,或者是网络状况不佳等外部原因

当应用发生crash时,如果只是你一个人使用的应用,那自然容易检测出原因,可是如果应用有广泛的使用者,面对市面上众多的Rom和机型,就需要一个个获取发生crash时的系统情况了,将异常信息记录下来并发送到服务器,供开发者了解情况并调试

Android提供有默认的异常处理方法,也可以自定义异常处理方法

在Thread类下有如下方法用来设置自定义异常处理器

public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
    Thread.defaultUncaughtHandler = handler;
}

当crash发生时,系统会回调UncaughtExceptionHandler的如下方法,我们就需要来重写该方法

public void uncaughtException(Thread thread, Throwable throwable){

}

因此,现在需要进行的步骤是:

1. 实现Thread.UncaughtExceptionHandler接口,自定义异常处理器

2. 重写uncaughtException方法

3. 在uncaughtException方法中将crash信息以及当前手机信息保存到文本中,然后将文本打包发送到服务器

新建CrashHandler类继承于Thread.UncaughtExceptionHandler

/**
 * Crash处理 CZY
 * Created by ZY on 2016/8/27.
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {

    //定义文件存放路径
    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashInfo/";

    //定义文件后缀
    private static final String FILE_NAME_SUFFIX = ".txt";

    //系统默认的异常处理器
    private Thread.UncaughtExceptionHandler defaultCrashHandler;

    private static final String TAG = "CrashHandler";

    private static CrashHandler crashHandler = new CrashHandler();

    //私有化构造函数
    private CrashHandler() {
    }

    //获取实例
    public static CrashHandler getInstance() {
        return crashHandler;
    }

    public void init() {
        defaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        //设置系统的默认异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        //记录异常信息到本地文本中
        dumpExceptionToSDCard(throwable);
        if (defaultCrashHandler != null) {
            //如果在自定义异常处理器之前,系统有自己的默认异常处理器的话,调用它来处理异常信息
            defaultCrashHandler.uncaughtException(thread, throwable);
        } else {
            Process.killProcess(Process.myPid());
        }
    }

    //记录异常信息到本地文本中
    private void dumpExceptionToSDCard(Throwable throwable) {
        //如果SD卡非正常挂载,则用Log输出异常信息
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            Log.e(TAG, "SD卡出错");
            return;
        }
        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        long currentTime = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(currentTime));
        //建立记录Crash信息的文本
        File file = new File(PATH + time + FILE_NAME_SUFFIX);
        try {
            PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            printWriter.println(time);
            dumpPhoneInfo(printWriter);
            printWriter.println();
            throwable.printStackTrace(printWriter);
            printWriter.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "记录Crash信息失败");
        }
    }

    //记录手机信息
    private void dumpPhoneInfo(PrintWriter printWriter) {
        //系统版本号
        printWriter.print("OS Version:");
        printWriter.print(Build.VERSION.RELEASE);
        printWriter.print("_");
        printWriter.println(Build.VERSION.SDK_INT);
        //硬件制造商
        printWriter.print("Vendor:");
        printWriter.println(Build.MANUFACTURER);
        //系统定制商
        printWriter.print("Brand:");
        printWriter.println(Build.BRAND);
    }

}

采用了单例模式,每个方法的作用也都注释了其作用

然后,选择在Application中初始化CrashHandler

所以需要自定义Application

/**
 * Created by ZY on 2016/8/27.
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        CrashHandler crashHandler = CrashHandler.getInstance();
        crashHandler.init();
    }

}

需要在AndroidManifest.xml文件中声明之 即在application标签下添加以下一行语句

android:name=".MyApplication"

此外,因为还涉及到了内存卡写操作,所以需要声明下权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

然后,在主布局文件中声明个按钮,在点击后抛出一个自定义异常

        findViewById(R.id.crashTest).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                throw new RuntimeException("自定义异常");
            }
        });

点击后程序异常退出,打开手机的文件内容管理器

可以看到多了一个CrashInfo文件夹

这里写图片描述

保存异常信息的文件

这里写图片描述

异常信息

这里写图片描述

这要,就获取到了异常信息,这里只是将信息保存到了SD卡上,在实际开发中再添加上传到服务器的操作即可

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏cmazxiaoma的架构师之路

IDEA入门(1)--lombok和Junit generator2插件的运用

1413
来自专栏逆向技术

win32程序之窗口程序,以及消息机制

  通过上一讲.我们了解了窗口其实是绘制出来的.而且是不断绘制的过程. 所以窗口的本质是绘制. 但是我们现在看到的窗口程序.都可以点击关闭按钮. 使用鼠标点击会...

642
来自专栏程序员的诗和远方

在React Native中优雅的使用iconfont

React Native大火大热,其中为了解决图标,易于修改,换颜色,高清等需求,iconfont的应用更是必不可少。 React Native中的ic...

3934
来自专栏Google Dart

AngularDart Material Design 记分卡 顶

(adsbygoogle = window.adsbygoogle || []).push({}); fun...

994
来自专栏james大数据架构

在ASPNET中使用JS集锦

(一).确认删除用法: 1. BtnDel.Attributes.Add("onclick","return confirm('"+"确认删除?"+"')")...

1837
来自专栏Java后端生活

Markdown的十个基本标签

1987
来自专栏我的小碗汤

Log4jConfigListener动态改变记录级别及实现

摘要: 线上的系统出现了bug,可能是请求的数据出现了问题,这个时候,日志就为我们提供了解决问题的办法。但是线上的产品系统,一般的优先级都在INFO之上,如果修...

894
来自专栏开心的学习之路

04 Nifty自定义带图片的下拉框

读了好久源代码,才搞明白怎么回事,其实现在回过头来想想很简单,主要是寻找的过程艰难。 自定义一个control 在resources里面新建一个文件夹MyCon...

2738
来自专栏Flutter入门到实战

模仿安卓源码,手写过时的方法兼容低版本

我们经常会使用getColor(R.color.XXX)获取颜色的资源文件,但是在安卓6.0开始,这个方法被标注为过时,推荐使用两个参数的方法替代,如下图所示:

492
来自专栏闻道于事

IDEA使用

最重要的: Ctrl+Shift+A  打开搜索 定位代码: 项目之间的跳转: ? 文件之间的跳转: 打开最近文件列表  Ctrl + E     打开最近修改...

2694

扫码关注云+社区