使用CrashHandler获取应用crash信息
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信息的更多相关文章
- android 之 Crash信息的持久化处理
需求: 持久化运行时异常的信息 1.CrashHandler.java import android.content.Context; import android.content.pm.Packag ...
- 在Android Studio中使用BaiduMap SDK实时获取当地位置信息
配置BaiduMap 环境 1.在百度API中新建自己的一个APP包名和APP名需要注意和自己Android Studio 中的包名和APP名保持一致: 2.百度地图中还需要填写一个SHA1 数字签名 ...
- Android_ 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法
转载时注明地址:http://blog.csdn.net/xiaanming/article/details/9344703 我们开发Android应用的时候,当出现Crash的时候,系统弹出一个警告 ...
- sql 2012中获取表的信息,包含字段的描述
1.获取数据库中的表 select name from sysobjects where type='U' 2.获取表字段(此处是Route表) Select name from syscolumns ...
- ThinPHP命名空间,连接数据库是要修改的配置文件,Model数据模型层,跨控制器调用,如何获取系统常量信息,
一.命名空间(主要是为了实现自动加载类) *命名空间(相当于虚拟的目录),为了让类有一个统一的文件夹来管理(可以自动加载'类'),每个文件都要有命名空间*tp如何做命名空间:*TP框架下有一个初始命名 ...
- 获取应用程序信息.h
//// 获取应用程序信息.h// IOS笔记// 一般会用来判断是否有新版本.是否需要强制更新 iOS的版本号,一个叫做Version,一个叫做Build,这两个值都可以在Xcode 中选中ta ...
- PHP获取当前服务器信息的基本语句
下面是PHP获取当前服务器信息的基本语句. PHP程式版本: <?PHP echo PHP_VERSION; ?> ZEND版本: <?PHP echo zend_version() ...
- C# 获取 mp3文件信息
C# 获取 mp3文件信息[包括:文件大小.歌曲长度.歌手.专辑] 第一种方式:[代码已验证] // http://bbs.csdn.net/topics/390392612 string fil ...
- Linux sysinfo获取系统相关信息
Linux中,可以用sysinfo来获取系统相关信息. #include <stdio.h> #include <stdlib.h> #include <errno.h& ...
随机推荐
- 【管理员已阻止你运行此应用】windows defender图标打叉,无法打开mmc.exe解决办法
今天开机遇到一个奇怪的问题,发现windows defender图标上面打了个×: 打开按照系统提示需要restart服务,但是无法重启服务,会出现错误,然后尝试手动重启服务,准备打开管理控制台mmc ...
- 番外:socketserver用法
进击のpython ***** 番外:socketserver使用 是不是被一般写法,多进程写法,多线程写法甚至是协程写法搞的不可开交 云里雾里,仿佛将要放弃~再配上服务器要服务多个客户端 完蛋了,全 ...
- 一步步教你用Prometheus搭建实时监控系统系列(二)——详细分析拉取和推送两种不同模式
前言 本系列着重介绍Prometheus以及如何用它和其周边的生态来搭建一套属于自己的实时监控告警平台. 本系列受众对象为初次接触Prometheus的用户,大神勿喷,偏重于操作和实战,但是重要的概念 ...
- Linux系统安装Samba共享服务器详解及安装配置
一.简介 Samba服务程序是一款基于SMB协议并由服务端和客户端组成的开源文件共享软件,实现了Linux和windows系统间的文件共享.SMB(Server Messages Block,信息服务 ...
- 4-Pandas之数据类型与数据筛选
一.数据类型 1.Pandas的数据类型主要结合了pandas和numpy两个模块中的数据类型,包括以下几种: float int bool datetime64[ns]------>日期类型 ...
- PHP arsort() 函数
------------恢复内容开始------------ 实例 对关联数组按照键值进行降序排序: <?php$age=array("Peter"=>"35 ...
- PHP fileatime() 函数
定义和用法 fileatime() 函数返回指定文件的上次访问时间. 如果成功,该函数将以 Unix 时间戳形式返回文件的上次访问时间.如果失败,则返回 FALSE. 语法 fileatime(fil ...
- 【问题记录】ajax dataType属性
最近整理代码,发现一些ajax dataType 属性值设置的问题.下面直接上代码说明下 前台ajax请求 $.ajax({ type: "get", dataType: &quo ...
- MyBatis辟邪剑谱
一 MyBatis简介 MyBatis是一个优秀的持久层框架 它对JDBC操作数据库的过程进行封装 开发者只需要关注SQL本身 而不需要花费精力去处理JDBC繁杂的过程代码 MyBatis将要执行的各 ...
- java动态代理——jvm指令集基本概念和方法字节码结构的进一步探究及proxy源码分析四
前文地址 https://www.cnblogs.com/tera/p/13336627.html 本系列文章主要是博主在学习spring aop的过程中了解到其使用了java动态代理,本着究根问底的 ...