专栏首页开发之途Android 获取应用Crash信息的方法

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 条评论
登录 后参与评论

相关文章

  • 在 Android 设备上搭建 Web 服务器

    一般而言,Android 应用在请求数据时都是以 Get 或 Post 等方式向远程服务器发起请求,那你有没有想过其实我们也可以在 Android 设备上搭建一...

    叶应是叶
  • Android SpannableString使用示例

    有时候可以看到一些文本承载了不同风格的样式,比如背景色、下划线、下标、附带表情图等等 其实这些都可以通过SpannableString来完成,通过为之设置不同...

    叶应是叶
  • Android RecyclerView的简便写法

    RecyclerView现在可以说是很常用了吧?RecyclerView自然是很方便的控件,但用多了有时候对一些重复性代码也是感觉挺麻烦的,于是乎我就将一些重复...

    叶应是叶
  • 一文了解web无状态会话token技术JWT

    目前web开发前后端已经算非常的普及了。前后端分离要求我们对用户会话状态要进行一个无状态处理。我们都知道通常管理用户会话是session。用户每次从服务器认证成...

    码农小胖哥
  • Flutter 拖拽控件Draggable看这一篇就够了

    Draggable组件有2个必须填写的参数,child参数是子控件,feedback参数是拖动时跟随移动的组件,用法如下:

    老孟程序员
  • C语言编程精华——《指针》

    C语言编程精华--《指针》 使用指针有两方面的优势: 1、用指针能够更好完成某些任务; 2、有些任务只能是用指针才能够完成。 一、指针定义 1、计算机的内存 计...

    企鹅号小编
  • ResNet压缩20倍,Facebook提出新型无监督模型压缩量化方法

    本文旨在解决类似 ResNet [1] 这类卷积网络的模型过大,推理速度慢的问题。相比较之前的量化方法,本文提出来一个向量量化方法,其主要思想是保存网络重建之后...

    机器之心
  • 业界 | 追一科技完成B轮2060万美元融资,创新工场领投

    机器之心
  • 物联网的未来可以在电脑中看到

    物联网IoT在早期展示了许多与PC相同的成长中的痛苦,潜在的潜力潜伏在几乎没有想象的未来应用程序中。 ? 我们正在达成IoT设备广泛使用的地步,但仍然需要付费(...

    首席架构师智库
  • SVN previous operation has not finished

    svn提交遇到恶心的问题,可能是因为上次cleanup中断后,进入死循环了。 错误如下: ? 解决方法:清空svn的队列 1.下载sqlite3.exe   ...

    hbbliyong

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动