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

/**
* Sets the default uncaught exception handler.
* This handler is invoked in case any Thread due to unhandled exception.
*
* @param handler
* The handler to set or null.
*/
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler){
Thread.defaultUncaughtHandler = handler;
}

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

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

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CrashHandler";
private static final boolean DEBUG = true; private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashTest/log/";
private static final String FILE_NAME = "crash";
private static final String FILE_NAME_SUFFIX = ".trace"; private static CrashHandler sInstance = new CrashHandler();
private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
private Context mContext; private CrashHandler(){
} public static CrashHandler getInstance(){
return sInstance;
} public void init(Context context){
mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
mContext = context.getApplicationContext();
} /**
* 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaught-
* thread为出现未捕获异常的线程,ex为未捕获的异常,有了这个ex,就可以得到异常信息
*/
@Override
public void uncaughtException(Thread thread, Throwable ex){
try{
//导入异常信息到SD卡中
dumpExceptionToSDCard(ex);
//这里可以上传异常信息到服务器,便于开发人员分析日志从而解决bug
uploadExceptionToServer();
}catch(IOException e){
e.printStackTrace();
} ex.printStackTrace();
//如果系统提供了默认的异常处理器,则交给系统去结束程序,否则就由自己结束自己
if(mDefaultCrashHandler != null){
mDefaultCrashHandler.uncaughtException(thread, ex);
}else{
android.os.Process.killProcess(android.os.Process.myPid());
}
} private void dumpExceptionToSDCard(Throwable ex) throws IOException{
//如果SD卡不存在或无法使用,则无法把异常信息写入SD卡
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
if(DEBUG){
Log.w(TAG, "sdcard unmounted,skip dump exception");
return;
}
} File dir = new File(PATH);
if(!dir.exists()){
dir.mkdirs();
}
long current = System.currentTimeMillis();
String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX); try{
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
pw.println(time);
dumpPhoneInfo(pw);
pw.println();
ex.printStackTrace(pw);
pw.close();
}catch(Exception e){
Log.e(TAG, "dump crash info failing");
}
} private void dumpPhoneInfo(PrintWriter pw)throws PackageManager.NameNotFoundException{
PackageManager pm = mContext.getPackageManager();
PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
pw.print("APP Version: ");
pw.print(pi.versionName);
pw.print('_');
pw.println(pi.versionCode); //Android版本号
pw.print("OS Version: ");
pw.print(Build.VERSION.RELEASE);
pw.print('_');
pw.println(Build.VERSION.SDK_INT); //手机制造商
pw.print("Vendor: ");
pw.println(Build.MANUFACTURER); //手机型号
pw.print("Model: ");
pw.println(Build.MODEL); //CPU架构
pw.print("CPU ABI: ");
pw.println(Build.CPU_ABI);
} private void uploadExceptionToServer(){
//TODO Upload Exception Message To Web Server
}
}

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

public class MainApplication extends MultiDexApplication {
private static MainApplication sInstance; @Override
public void onCreate() {
super.onCreate();
sInstance = this;
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(this);
} public static MainApplication getInstance(){
return sInstance;
}

使用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. npm 使用报错合集

    1.Unexpected end of JSON input while parsing near '...e,"directories":{},"d' 这个问题经常会出 ...

  2. Android应用内部实现多语言,一键切换语言,国际化适配

    1.首先提供多语言对应的string值 如en对应英语, fr对应法语 两个文件中包含同样的key, 对应不同的语言的value 2.java代码相应用户切换语言动作 private static v ...

  3. vb教程图文并茂

    https://blog.csdn.net/baimafujinji/article/details/70198953

  4. 利用Data vault对数据仓库建模

    简介 国内关于Data Vault的信息很少,所以决定写点什么,纯粹都是自己在这个行业10多年的摸爬滚打.不过为了效率,尽量做到简短,直接上干货.对于各个细节大家有不同的理解欢迎来讨论. 数据仓库建模 ...

  5. Android多线程--AsyncTask

    常见的多线程方法有: 继承Thread类 实现Runnable接口 Handler AsyncTask HandlerThread 1.定义 一个Android已经封装好的轻量级异步类 属于抽象类,即 ...

  6. ken桑带你读源码之scrapy downloadermiddlewares

    downloadermiddlewares  文件夹是下载中间件 其中  process_request   还没请求时的处理函数 process_response  请求之后的处理函数 chunke ...

  7. jquery判断radio是否选中

    微交易-实体系统 微交易-虚拟系统   <div class="system"> <div class="systemt"> <l ...

  8. matpltlib 示例

    matplotlib https://matplotlib.org/index.html

  9. pass 出错问题

    ''' a = 10 b = 8 print("a>b") if a>b else pass pass 为何报错问题: 第一部分:print 第二部分:("a ...

  10. Python os.fstat() 方法

    概述 os.fstat() 方法用于返回文件描述符fd的状态,类似 stat().高佣联盟 www.cgewang.com Unix,Windows上可用. fstat 方法返回的结构: st_dev ...