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. springboot手动事务回滚

    亲测在使用@Transactional.@Transactional(rollbackFor = Exception.class)及catch异常之后 throw new RuntimeExcepti ...

  2. asp.net core 动态更新 appsetting.json方法

    如何将值更新到appsetting.json? 我正在使用官方文档中IOptions描述的模式. 当我从中读取值时appsetting.json,这可以正常工作,但是如何更新值并将更改保存回来apps ...

  3. 洛谷p1120小木棍(剪枝优化)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  4. 高精度进制转换(poj1220)

    常规短除法原理 高精度进制转换是对于特别大的数字来说的,当数字特别大时,难以进行除法和取余的操作,此时通过字符串模拟的办法可以解决. #include <iostream> #includ ...

  5. 3分钟看懂Python后端必须知道的Django的信号机制!

    概念 django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者( ...

  6. MySQL组复制MGR(一)-- 技术概述

    (一)复制技术的发展 MySQL的复制技术主要经历了异步主从复制,半同步复制,组复制(Group Replication)3个阶段. (1)传统的异步主从复制 传统的MySQL提供了一种简单的主从复制 ...

  7. 如何在sed中使用变量,两种方法

    第一 在sed条件中是不认识变量取值的 sed '/$x/d' test 所以要想它能够识别变量 sed "/$x/d/" test 方法简单就是把"单引号"变 ...

  8. 你不知道的Java引用

    什么是引用   引用就是保存着一块地址(门牌号)的对象,就像C语言的指针那样,引用可以传递某个数据的地址,如果我们想拿到某一条数据,就要先找到他的地址,然后告诉计算机我去拿这个地址的数据,最后计算机就 ...

  9. 第十章 函数式接口&Stream流

    10.1.函数式接口 10.1.1.概述 有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解 10.1.2.函 ...

  10. SQLyog无操作一段时间后重新操作会卡死问题(解决办法)

    这种是因为一段时间不操作后,服务器将空闲连接丢弃了,而客户端(sqlyog)不知道,导致长时间无响应,而超时之后,sqlyog 使用了新的连接,所以又可以顺畅操作了. 将会话空闲时间默认改为自定义,填 ...