Android应用不可避免会发生crash,也称之为崩溃。发生原因可能是由于Android系统底层的bug,也可能是由于不充分的机型适配或者是糟糕的网络情况。当crash发生时,系统会kill掉正在执行的程序,现象就是闪退或者提示用户程序已停止运行。更糟糕的是,当用户发生了crash,开发者却无法得知程序为何crash,因此需要知道用户当时的crash信息。为此Android提供了处理这类问题的方法,即Thread类中的一个方法setDefaultUncaughtExceptionHandler

  1. /**
  2. * Sets the default uncaught exception handler.
  3. * This handler is invoked in case any Thread due to unhandled exception.
  4. *
  5. * @param handler
  6. * The handler to set or null.
  7. */
  8. public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler){
  9. Thread.defaultUncaughtHandler = handler;
  10. }

  当crash发生的时候,系统就会回调UncaughtExceptionHandler的uncaughtException方法,在uncaughtException方法中就可以获取到异常信息。

  下面是一个典型的异常处理器的实现:

  1. public class CrashHandler implements Thread.UncaughtExceptionHandler {
  2. private static final String TAG = "CrashHandler";
  3. private static final boolean DEBUG = true;
  4. private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashTest/log/";
  5. private static final String FILE_NAME = "crash";
  6. private static final String FILE_NAME_SUFFIX = ".trace";
  7. private static CrashHandler sInstance = new CrashHandler();
  8. private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
  9. private Context mContext;
  10. private CrashHandler(){
  11. }
  12. public static CrashHandler getInstance(){
  13. return sInstance;
  14. }
  15. public void init(Context context){
  16. mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
  17. Thread.setDefaultUncaughtExceptionHandler(this);
  18. mContext = context.getApplicationContext();
  19. }
  20. /**
  21. * 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaught-
  22. * thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,就可以得到异常信息
  23. */
  24. @Override
  25. public void uncaughtException(Thread thread, Throwable ex){
  26. try{
  27. //导入异常信息到SD卡中
  28. dumpExceptionToSDCard(ex);
  29. //这里可以上传异常信息到服务器,便于开发人员分析日志从而解决bug
  30. uploadExceptionToServer();
  31. }catch(IOException e){
  32. e.printStackTrace();
  33. }
  34. ex.printStackTrace();
  35. //如果系统提供了默认的异常处理器,则交给系统去结束程序,否则就由自己结束自己
  36. if(mDefaultCrashHandler != null){
  37. mDefaultCrashHandler.uncaughtException(thread, ex);
  38. }else{
  39. android.os.Process.killProcess(android.os.Process.myPid());
  40. }
  41. }
  42. private void dumpExceptionToSDCard(Throwable ex) throws IOException{
  43. //如果SD卡不存在或无法使用,则无法把异常信息写入SD卡
  44. if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  45. if(DEBUG){
  46. Log.w(TAG, "sdcard unmounted,skip dump exception");
  47. return;
  48. }
  49. }
  50. File dir = new File(PATH);
  51. if(!dir.exists()){
  52. dir.mkdirs();
  53. }
  54. long current = System.currentTimeMillis();
  55. String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
  56. File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
  57. try{
  58. PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
  59. pw.println(time);
  60. dumpPhoneInfo(pw);
  61. pw.println();
  62. ex.printStackTrace(pw);
  63. pw.close();
  64. }catch(Exception e){
  65. Log.e(TAG, "dump crash info failing");
  66. }
  67. }
  68. private void dumpPhoneInfo(PrintWriter pw)throws PackageManager.NameNotFoundException{
  69. PackageManager pm = mContext.getPackageManager();
  70. PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
  71. pw.print("APP Version: ");
  72. pw.print(pi.versionName);
  73. pw.print('_');
  74. pw.println(pi.versionCode);
  75. //Android版本号
  76. pw.print("OS Version: ");
  77. pw.print(Build.VERSION.RELEASE);
  78. pw.print('_');
  79. pw.println(Build.VERSION.SDK_INT);
  80. //手机制造商
  81. pw.print("Vendor: ");
  82. pw.println(Build.MANUFACTURER);
  83. //手机型号
  84. pw.print("Model: ");
  85. pw.println(Build.MODEL);
  86. //CPU架构
  87. pw.print("CPU ABI: ");
  88. pw.println(Build.CPU_ABI);
  89. }
  90. private void uploadExceptionToServer(){
  91. //TODO Upload Exception Message To Web Server
  92. }
  93. }

  上面的CrashHandler使用也很简单,可以选择在Application初始化的时候为线程设置CrashHandler,如下所示:

  1. public class MainApplication extends MultiDexApplication {
  2. private static MainApplication sInstance;
  3. @Override
  4. public void onCreate() {
  5. super.onCreate();
  6. sInstance = this;
  7. CrashHandler crashHandler = CrashHandler.getInstance();
  8. crashHandler.init(this);
  9. }
  10. public static MainApplication getInstance(){
  11. return sInstance;
  12. }

使用CrashHandler获取应用crash信息的更多相关文章

  1. android 之 Crash信息的持久化处理

    需求: 持久化运行时异常的信息 1.CrashHandler.java import android.content.Context; import android.content.pm.Packag ...

  2. 在Android Studio中使用BaiduMap SDK实时获取当地位置信息

    配置BaiduMap 环境 1.在百度API中新建自己的一个APP包名和APP名需要注意和自己Android Studio 中的包名和APP名保持一致: 2.百度地图中还需要填写一个SHA1 数字签名 ...

  3. Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法

    转载时注明地址:http://blog.csdn.net/xiaanming/article/details/9344703 我们开发Android应用的时候,当出现Crash的时候,系统弹出一个警告 ...

  4. sql 2012中获取表的信息,包含字段的描述

    1.获取数据库中的表 select name from sysobjects where type='U' 2.获取表字段(此处是Route表) Select name from syscolumns ...

  5. ThinPHP命名空间,连接数据库是要修改的配置文件,Model数据模型层,跨控制器调用,如何获取系统常量信息,

    一.命名空间(主要是为了实现自动加载类) *命名空间(相当于虚拟的目录),为了让类有一个统一的文件夹来管理(可以自动加载'类'),每个文件都要有命名空间*tp如何做命名空间:*TP框架下有一个初始命名 ...

  6. 获取应用程序信息.h

    ////  获取应用程序信息.h//  IOS笔记// 一般会用来判断是否有新版本.是否需要强制更新 iOS的版本号,一个叫做Version,一个叫做Build,这两个值都可以在Xcode 中选中ta ...

  7. PHP获取当前服务器信息的基本语句

    下面是PHP获取当前服务器信息的基本语句. PHP程式版本: <?PHP echo PHP_VERSION; ?> ZEND版本: <?PHP echo zend_version() ...

  8. C# 获取 mp3文件信息

    C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612   string fil ...

  9. Linux sysinfo获取系统相关信息

    Linux中,可以用sysinfo来获取系统相关信息. #include <stdio.h> #include <stdlib.h> #include <errno.h& ...

随机推荐

  1. nginx配置多个图片访问路径

    需求:vue项目打包的时候 会将项目中的一些图片打包到/dist/static/images下,但是有时候会有一些很大的图片,需要单独存放至别的文件夹比如/home/di-img下,不能被打倒包内.部 ...

  2. vue.js全局组件和局部组件区别

    在id=‘#app’,加入<pl>标签,但也访问不了局部chil组件: 在id=‘#div0’,加入<as>标签,但能访问到全局组件

  3. 简单了解InnoDB底层原理

    存储引擎 很多文章都是直接开始介绍有哪些存储引擎,并没有去介绍存储引擎本身.那么究竟什么是存储引擎?不知道大家有没有想过,MySQL是如何存储我们丢进去的数据的? 其实存储引擎也很简单,我认为就是一种 ...

  4. springmvc的原理与流程

    springMVC中的几个组件: 前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU. 处理器映射器(HandlerMapping):根据URL去查找处理器 处理 ...

  5. PHP is_link() 函数

    定义和用法 The is_link() 函数检查指定的文件是否是一个连接. 如果文件是一个连接,该函数返回 TRUE. 语法 is_link(file) 参数 描述 file 必需.规定要检查的文件. ...

  6. PHP preg_replace() 函数

    preg_replace 函数执行一个正则表达式的搜索和替换.高佣联盟 www.cgewang.com 语法 mixed preg_replace ( mixed $pattern , mixed $ ...

  7. mapstruct解放Java对象转换

    摘要 当前web后端开发,都是使用多层工程结构,需要在VO,BO,DTO,DO等各种数据结构中相互转换.这些转换代码都是些比较简单的字段映射,类型转换,重复性工作比较高,可以使用一些工具解放我们的双手 ...

  8. win10 安装tensorflow2.0 GPU版本遇到的坑

          背景:我的机器上tensorflow 1.14 & 2.0,这俩版本都有,之前都是用1.14版本,今天试一下2.0尝尝鲜, 结果就掉坑去了 把CUDA10.1 和 cudnn 安装 ...

  9. 【SDOI2012】Longge 的问题 题解(欧拉函数)

    前言:还算比较简单的数学题,我这种数学蒟蒻也会做QAQ. --------------- 题意:求$\sum\limits_{i=1}^n gcd(i,n)$的值. 设$gcd(i,n)=d$,即$d ...

  10. 从零搭建Spring Boot脚手架(1):开篇以及技术选型

    1. 前言 目前Spring Boot已经成为主流的Java Web开发框架,熟练掌握Spring Boot并能够根据业务来定制Spring Boot成为一个Java开发者的必备技巧,但是总是零零碎碎 ...