1.整体分析

1.1.源代码如下,可以直接Copy。  

public class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String TAG = "异常处理";
private static final boolean DEBUG = true; private static final String PATH = Environment.getExternalStorageDirectory().getPath() +
"/test/log/";
private static final String FILE_NAME = "crash"; //log文件的后缀名
private static final String FILE_NAME_SUFFIX = ".txt"; 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);
//获取Context,方便内部使用
mContext = context.getApplicationContext(); } /**
* 这个是最关键的函数,当程序中有未被捕获的异常,系统将会自动调用#uncaughtException方法
* 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 {
Process.killProcess(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));
//以当前时间创建log文件
File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
if (!file.exists()) {
Log.i(TAG, "文件名称为:"+file.getName());
}else{
Log.i(TAG, "文件名称为:"+file.getName());
} try {
if(file.createNewFile()){
Log.i(TAG, "文件创建成功:名称为:"+file.getName());
}
if(file.exists()){
Log.i(TAG, "文件exists");
}
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 failed");
}
} 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 Your Web Server
} }

1.2.实现的方法如下

  • 继承了Thread.UncaughtExceptionHandler,所以实现override方法uncaughtException
  • 将异常信息写入SD卡,实现dumpExceptionToSDCard
  • 打印应用的版本名称和版本号和手机制造商、手机型号及cpu架构
  • 上传到服务器,这个函数要看情况需不需要 

1.3.需要动态申请写文件的权限。

  参考文章:http://blog.csdn.net/wuqingyou_w/article/details/60138807

private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE" }; public static void verifyStoragePermissions(Activity activity) { try {
//检测是否有写的权限
int permission = ActivityCompat.checkSelfPermission(activity,
"android.permission.WRITE_EXTERNAL_STORAGE");
if (permission != PackageManager.PERMISSION_GRANTED) {
// 没有写的权限,去申请写的权限,会弹出对话框
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
}
} catch (Exception e) {
e.printStackTrace();
}
}

  将这个方法放在onCreate或者其他必然执行的地方即可。

2.局部分析

2.1.首先是成员变量

  

  TAG用来调试时输出的。

  DEBUG是为了判断当前项目处于开发模式还是调试模式。

  PATH是日志文件存储路径,前面不能变,后面随意。

  注意点:我的手机一开始我找不到这个文件。

  因为我在Logcat上输出了这个Environment.getExternalStorageDirectory().getPath为

    /storage/emulated/0(不同手机可能不同)

  然后我在手机上真的找到了这个路径,但是这个目录下始终没有日志文件

  最后我才知道这个Environment.getExternalStorageDirectory().getPath就是手机的主目录

  在主目录下就有新建的文件夹以及目录了。

  FILE_NAME是日志文件的前缀

  FILE_NAME_SUFFIX是日志文件的后缀

  sInstance是新建的CrashHandler的一个实例

  mDefaultCrashHandler是系统默认的异常处理,系统会终止当前的异常程序

  mContext是上下文

2.2.构造方法

  

2.3.获取单例

  

2.4.完成初始化工作

  

  还是要获取系统默认的异常处理器

  然后将当前实例设为系统默认的异常处理器,这样每次都会先执行这里了

  获取一下上下文,方便内部使用

2.5.这里是实现的接口方法uncaughtException

  

  可以看到,这里先将信息导出到SD卡中,然后上传异常信息到服务器(这里需要看情况写了)

  然后交给系统默认的异常处理器去处理后事。没有默认的,就自己结束自己吧。

2.6.如何写到SD卡中呢?

  

  

  首先获取SD卡默认路径

  先利用file.mkdirs()方法来创建一系列的路径,mkdir()只能创建当前目录的文件夹,mkdirs()可以无限了。

  然后利用系统当前时间可以创建唯一的名称

  然后利用createNewFile()方法,可以创建一个文件了

  之后利用PrintWriter来向文件中写入数据了。

  PrintWriter pw=new PrintWriter(new BufferedWriter(new FileWriter(file)))这种方法来创建流

  然后可以用pw.println()向文件中写入数据了。

  最后要将pw关闭。

2.7.如何向文件中写入手机信息?

  

  这里利用上下文获取包管理器,然后有包管理器获取包信息,然后就可以获取版本号及名称。

  手机制造商和手机型号和cup架构需要Build类获取。

2.8.上传到服务器需要自己看情况写

  

3.使用方法及效果

3.1.首先在项目的Application中初始化

  在onCreate函数中添加==>

  CrashHandler.getInstance().init(this);

3.2.然后只要发生异常,都会将异常信息发送到日志文件

    

  

Android 工具类 异常处理类CrashHandler的更多相关文章

  1. 29个android开发常用的类、方法及接口

    在安卓开发中,我们常常都需要借助各种各样的方法.类和接口来实现相关功能.提升开发效率,但对于初学者而言,什么时候该用什么类.方法和接口呢?下面小编整理了29个,日常开发中比较常用的类.方法.接口及其应 ...

  2. 多测师讲解常用的测试工具分为10类_高级讲师肖sir

    我们将常用的测试工具分为10类. 1. 测试管理工具 2. 接口测试工具 3. 性能测试工具 4. C/S自动化工具 5.白盒测试工具 6.代码扫描工具 7.持续集成工具 8.网络测试工具 9.app ...

  3. Android 通过 Intent 传递类对象或list对象

    (转:http://www.cnblogs.com/shaocm/archive/2013/01/08/2851248.html) Android中Intent传递类对象提供了两种方式一种是 通过实现 ...

  4. php 异常处理类

    PHP具有很多异常处理类,其中Exception是所有异常处理的基类. Exception具有几个基本属性与方法,其中包括了: message 异常消息内容code 异常代码file 抛出异常的文件名 ...

  5. 命令行下使用javah命令生成.h文件,出现“错误: 无法访问android.app.Activity 找不到android.app.Activity的类文件”的解决方法

    在学习NDK中,当我在项目的bin/classes目录下使用javah命令生成头文件时,出现了“错误: 无法访问android.app.Activity 找不到android.app.Activity ...

  6. android SQLite使用SQLiteOpenHelper类对数据库进行操作

    android SQLite使用SQLiteOpenHelper类对数据库进行操作 原文: http://byandby.iteye.com/blog/835580

  7. Android 通过 Intent 传递类对象

    Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...

  8. Spring MVC自定义统一异常处理类,并且在控制台中输出错误日志

    在使用SimpleMappingExceptionResolver实现统一异常处理后(参考Spring MVC的异常统一处理方法), 发现出现异常时,log4j无法在控制台输出错误日志.因此需要自定义 ...

  9. [C#] 常用工具类——系统日志类

    using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespa ...

随机推荐

  1. Python开发环境Wing IDE之Search in Files工具详解

    Search in Files工具是Wing IDE中最强大的搜索选项.它支持磁盘.项目,打开编辑器,或其它文件集的多文件批量搜索.它还可以使用通配符搜索,并可以做基于正则表达式的搜索/替换. 建议用 ...

  2. APP常用检测

    检测设备.微信平台和app是否安装 // 检测是否安装了APP var isappinstalled = (function () { ); }()), // 检测ios设备 isIOS = (fun ...

  3. Chromium源码系列一:Chromium简介及源代码获取和编译

    Chromium源码系列一:Chromium简介及源代码获取和编译 Chromium简介 ​ Chromium是一个由Google主导开发的网页浏览器,以BSD许可证等多重自由版权发行并开放源代码.C ...

  4. dell omsa管理工具

    dell服务器raid管理工具 lsiutil dell sas6i/r MegaCli dell prec omsa管理raid分区 显示物理硬盘信息 omreport storage pdisk ...

  5. redis笔记(三)

     redis配置文件 配置文件对单位大小写不敏感 tcp-backlog  511   高并发环境连接数 tcp-keepalive   单位为秒 0 表示不会进行keepalive检测,,,建议设置 ...

  6. 在android开发中如何使用JavaMail程序

    javaMail,是提供给开发者处理电子邮件相关的编程接口.它是Sun发布的用来处理email的API.它可以方便地执行一些常用的邮件传输.我们可以基于JavaMail开发出类似于Microsoft  ...

  7. robotframework实战三--自定义关键字

    在rf的实战1中,我的登录获取验证码就使用了自定义关键字,具体怎么做的,如下 1.新建文件夹 新建一个文件夹,我的MyLibrary,并且存放在site-packages下 2.编写代码 在pytho ...

  8. 最小堆的维护,POJ(2051)

    题目链接:http://poj.org/problem?id=2051 ///维持最小堆(优先队列)POJ2051 #include <iostream> #include <str ...

  9. 2018.9.3 CEP课程总结

    什么是CEP课程? 职业生涯规划课程 蓝桥介绍 立人达人 全人教育 人文 重视人 尊重人 关心人 爱护人 人才 人格 简历的制作 找工作的流程? 1.简历的准备------>投发简历(自己投.老 ...

  10. 下载Xcode历史版本方法

    1.打开链接:https://developer.apple.com/download/more 进入页面 2.在搜索框输入Xcode,回车搜索.如图,找到各种版本Xcode 搜索Xcode 3.双击 ...