Android CrashHandler
package jason.android.utils; import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast; import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; /**
* UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告.
*
* @author user
*
*/
public class MyCrashHandler implements UncaughtExceptionHandler { public static final String TAG = "MyCrashHandler"; //系统默认的UncaughtException处理类
private Thread.UncaughtExceptionHandler mDefaultHandler;
//CrashHandler实例
private static MyCrashHandler INSTANCE = new MyCrashHandler();
//程序的Context对象
private Context mContext;
//用来存储设备信息和异常信息
private Map<String, String> infos = new HashMap<String, String>(); //用于格式化日期,作为日志文件名的一部分
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); /** 保证只有一个CrashHandler实例 */
private MyCrashHandler() {
} /** 获取CrashHandler实例 ,单例模式 */
public static MyCrashHandler getInstance() {
return INSTANCE;
} /**
* 初始化
*
* @param context
*/
public void init(Context context) {
mContext = context;
//获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
//设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
} /**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
//退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
} /**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//使用Toast来显示异常信息
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
Looper.loop();
}
}.start();
//收集设备参数信息
collectDeviceInfo(mContext);
//保存日志文件
saveCrashInfo2File(ex);
return true;
} /**
* 收集设备参数信息
* @param ctx
*/
public void collectDeviceInfo(Context ctx) {
try {
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
if (pi != null) {
String versionName = pi.versionName == null ? "null" : pi.versionName;
String versionCode = pi.versionCode + "";
infos.put("versionName", versionName);
infos.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
Log.e(TAG, "an error occured when collect package info", e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
Log.d(TAG, field.getName() + " : " + field.get(null));
} catch (Exception e) {
Log.e(TAG, "an error occured when collect crash info", e);
}
}
} /**
* 保存错误信息到文件中
*
* @param ex
* @return 返回文件名称,便于将文件传送到服务器
*/
private String saveCrashInfo2File(Throwable ex) { StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key + "=" + value + "\n");
} Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result);
try {
long timestamp = System.currentTimeMillis();
String time = formatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String path = "/sdcard/crash/";
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(path + fileName);
fos.write(sb.toString().getBytes());
Log.e("ytr",sb.toString());
fos.close();
}
return fileName;
} catch (Exception e) {
Log.e(TAG, "an error occured while writing file...", e);
}
return null;
}
}
Android CrashHandler的更多相关文章
- Android中处理崩溃异常CrashHandler
来源:http://blog.csdn.net/liuhe688/article/details/6584143 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程 ...
- Android 工具类 异常处理类CrashHandler
1.整体分析 1.1.源代码如下,可以直接Copy. public class CrashHandler implements Thread.UncaughtExceptionHandler { pr ...
- Android 捕获异常并在应用崩溃后重启应用
问题概述: 在Android应用开发中,偶尔会因为测试的不充分导致一些异常没有被捕获,这时应用会出现异常并强制关闭,这样会导致很不好的用户体验,为了解决这个问题,我们需要捕获相关的异常并做处理. 首先 ...
- Android中处理崩溃异常
转自:http://my.eoe.cn/817027/archive/17997.html 大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不 ...
- Android 对程序异常崩溃的捕捉
转载博客:http://blog.csdn.net/i_lovefish/article/details/17719081 以下为异常捕捉处理代码: import java.io.BufferedRe ...
- [Android]从Launcher开始启动App流程源码分析
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5017056.html 从Launcher开始启动App流程源码 ...
- Android 高级面试题及答案
一 性能优化 1.如何对 Android 应用进行性能分析 android 性能主要之响应速度 和UI刷新速度. 可以参考博客:Android系统性能调优工具介绍 首先从函数的耗时来说,有一个工具Tr ...
- Android中处理崩溃异常和记录日志
大家都知道,现在安装Android系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了 ...
- Android程序crash处理
Android程序crash处理 时间 2014-11-24 13:45:37 CSDN博客 原文 http://blog.csdn.net/allen315410/article/details ...
随机推荐
- Linux学习-循环执行的例行性工作排程
循环执行的例行性工作排程则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的例行性工作,因此这个系统服务是默认启动的. 另外, 由于使用者自己也可以进行例行性工 ...
- Android开发——AsyncTask的使用以及源码解析
.AsyncTask使用介绍 转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52172248 AsyncTask封装了Thread和 ...
- luogu3808 luogu3796 AC自动机(简单版) AC自动机(加强版)
纪念一下我一晚上写了八遍AC自动机 这是加强版的: #include <iostream> #include <cstring> #include <cstdio> ...
- python-高级编程-01
[1] 列表推导 问题 我们需要一个[2,4,6,8] 这样的列表 传统写法 res = [] for i in range(10): if i %2 == 0:res.append(i) print ...
- PHP smarty模版引擎基本安装
环境: PHP5.2 以上版本 先去官网下载smarty模版引擎的库文件到你的电脑或服务器上 smarty官方网站库文件下载地址: https://www.smarty.net/download 下 ...
- 博客笔记(blog notebook)
1. 机器学习 2. NLP 3. code 实际好人 实际坏人 预测百分比 预测好人 \(p_GF^c(s_c\|G)\) \(p_BF^c(s_c\|B)\) \(F^c(s_c)\) 预测坏人 ...
- iOS-----5分钟学会枚举的正确使用姿势-Enumeration宏
前言 Enum,枚举,相信大部分编程语言都有对应的枚举类型,功能可能有多有少,但是枚举最核心的功能是 “规范的定义代码中的状态.状态码.选项”. 状态.状态码.选项 什么是状态:同时只能出现一个值(状 ...
- FZU——2111Min Number(多次交换得到最小数,水题)
Problem 2111 Min Number Accept: 760 Submit: 1516 Time Limit: 1000 mSec Memory Limit : 32768 KB ...
- HDU-2234 无题I
为每个状态定义两个函数S和H,分别表示当前状态到列一致和行一致的目标状态的最少操作次数. 然后有了估价函数F=Min(S,H)就可以IDA*了. #include <cstdio> #in ...
- Jersey实现Client端:GET/PUT/POST/DELETE
原文地址:Jersey客户端API调用REST风格的Web服务 [节选] 要开始使用 Jersey 客户端 API,你首先需要创建一个 com.sun.jersey .api.client.Clien ...