需求: 持久化运行时异常的信息

1.CrashHandler.java

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
import android.widget.Toast; import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map; /**
* 保存运行时异常的信息到手机上
* TODO 异常会保存3次, 应用会重启两次,这个不知道什么原因
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler { private final String FILE_NAME_FORMAT = "yyyy_MM_dd";
private final String FILE_NAME_PREFIXES = "crash_";
private final String FILE_NAME_EXTENSION = ".log";
private final String CRASH_TIME_FORMAT = "[yyyy-MM-dd HH:mm:ss:sss]";
private final String PARENT_DIRECTORY_NAME = "logs"; private Context mContext;
private Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler; /** 文件路径 */
private String filePath;
private String fileName; ///////////////////////////////////////////////////////////////////////////
// 单例模式
private static CrashHandler mInstance = new CrashHandler(); private CrashHandler() {} public static CrashHandler getInstance() {
return mInstance;
}
/////////////////////////////////////////////////////////////////////////// /** 在 自定义的Application 中 调用此方法即可 */
public void init(Context context) {
mContext = context;
filePath = mContext.getExternalFilesDir(PARENT_DIRECTORY_NAME) + File.separator;
fileName = FILE_NAME_PREFIXES + new SimpleDateFormat(FILE_NAME_FORMAT).format(System.currentTimeMillis()) + FILE_NAME_EXTENSION;
defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
} /** 异常发生时,系统回调的函数,我们在这里处理一些操作 */
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// 如果没有自定义处理方式就使用系统的方式
if (!handleException(ex) && defaultUncaughtExceptionHandler != null) {
defaultUncaughtExceptionHandler.uncaughtException(thread, ex);
} else {
// 让线程停止一会是为了显示Toast信息给用户,然后Kill程序
SystemClock.sleep(1000);
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
}
} /** 自定义 crash 处理 */
private boolean handleException(Throwable ex) {
if (ex == null) return true;
// 保存信息
saveInfo(mContext, ex); // 显示提示信息,需要在线程中显示Toast
new Thread(new Runnable() { @Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "很抱歉,程序遭遇异常,即将退出!", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start(); return true;
} /** 保存数据 */
private String saveInfo(Context context, Throwable ex) {
StringBuffer sb = new StringBuffer("\n");
// crash 的时间
sb.append("crashTime = ").append(new SimpleDateFormat(CRASH_TIME_FORMAT).format(System.currentTimeMillis())).append("\n");
// 设备信息
for (Map.Entry<String, String> entry : obtainSimpleInfo(context).entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key).append(" = ").append(value).append("\n");
}
// 异常信息
sb.append(obtainExceptionInfo(ex));
// 数据存储
File dir = new File(filePath);
if (!dir.exists()) dir.mkdir();
try {
FileOutputStream fos = new FileOutputStream(filePath + fileName, true); // 追加的方式
fos.write(sb.toString().getBytes());
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
} return fileName;
} /** 获取设备信息 */
private HashMap<String, String> obtainSimpleInfo(Context context) {
HashMap<String, String> map = new HashMap<String, String>();
PackageManager mPackageManager = context.getPackageManager();
PackageInfo mPackageInfo = null;
try {
mPackageInfo = mPackageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
} map.put("versionName", mPackageInfo.versionName);
map.put("versionCode", "" + mPackageInfo.versionCode); map.put("MODEL", "" + Build.MODEL);
map.put("SDK_INT", "" + Build.VERSION.SDK_INT);
map.put("PRODUCT", "" + Build.PRODUCT); return map;
} /** 获取 crash 信息 */
private String obtainExceptionInfo(Throwable throwable) {
StringWriter mStringWriter = new StringWriter();
PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
throwable.printStackTrace(mPrintWriter);
mPrintWriter.close();
return mStringWriter.toString();
} }

2.自定义的Application 中注册

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(this);
throw new NullPointerException("test crash " + android.os.Process.myPid());
}
}

3.adb shell cat /sdcard/Android/data/<package_name>/files/logs/crash_2016_04_20.log

android 之 Crash信息的持久化处理的更多相关文章

  1. 获取Android崩溃crash信息并写入日志发送邮件

    一.实现Thread.UncaughtExceptionHandlerUnChecked异常发生时,由于没有相应的try…catch处理该异常对象,所以Java运行环境将会终止,程序将退出,也就是我们 ...

  2. 保留全部Android crash信息

    保留全部Android crash信息 framework/base/core/java/com/android/internal/os/RuntimeInit.java 又一次以下这个函数,增加自己 ...

  3. Android怎样捕获应用的crash信息

    转载请注明出处:http://blog.csdn.net/fishle123/article/details/50823358 我们的应用不可避免的会发生crash,假设是在调试阶段,我们能够使用Lo ...

  4. Android程序crash处理

    Android程序crash处理 时间 2014-11-24 13:45:37  CSDN博客 原文  http://blog.csdn.net/allen315410/article/details ...

  5. Android程序Crash时的异常上报

    转载请注明来源:http://blog.csdn.net/singwhatiwanna/article/details/17289479 前言 大家都知道,android应用不可避免的会发生crash ...

  6. Android Native crash日志分析

    在Android应用crash的类型中,native类型crash应该是比较难的一种了,因为大家接触的少,然后相对也要多转几道工序,所有大部分对这个都比较生疏.虽然相关文章也有很多了,但是我在刚开始学 ...

  7. 使用CrashHandler获取应用crash信息

      Android应用不可避免会发生crash,也称之为崩溃.发生原因可能是由于Android系统底层的bug,也可能是由于不充分的机型适配或者是糟糕的网络情况.当crash发生时,系统会kill掉正 ...

  8. I.MX6 android 获取framebuffer信息

    /******************************************************************************** * I.MX6 android 获取 ...

  9. Android内存等信息

    1. Linux中proc目录下文件详解 http://wenku.baidu.com/view/2ce89f00a6c30c2259019ef1.html 2. Android系统/proc目录详解 ...

随机推荐

  1. js 事件监听封装

    var eventUtil={//添加句柄 //element,节点 //type,事件类型 //handler,函数 addHandler:function(element,type,handler ...

  2. Docker数据管理

    用户在使用Docker的过程中,往往需要能查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据共享,这必然涉及到Docker的数据管理. 容器中管理数据主要有两种方式: ...

  3. SSH原理与运用(一)和(二):远程登录 RSA算法原理(一)和(二)

    SSH原理与运用(一)和(二):远程登录  RSA算法原理(一)和(二) http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html ht ...

  4. JBOSS /invoker/JMXInvokerServlet 利用工具 .

    链接: http://pan.baidu.com/s/1F8bMI 密码: 1h2r 工具使用说明 1. 查看系统名称 java -jar jboss_exploit_fat.jar -i http: ...

  5. Glossary of view transformations

    Glossary of view transformations The following terms are used to define view orientation, i.e. trans ...

  6. cocos2dx 3.x以上版本搭建Mac环境(百分百可行)

    近期由于工作的原因,有机会接触了游戏行业,说实话,本人学程序最原始的初衷就是想做游戏,于是就创建了一篇cocos2d-x的分类来记录我在学习cocos2d-x的成长过程. 首先第一篇,想学cocos2 ...

  7. 成员变量NSString类型指针的属性为什么用copy(属性)

    创建一个分类Person设置属性@property(nonatomic,strong) NSString * name; 在- (void)viewDidLoad 中打印测试 name的属性是stro ...

  8. django url 软编码

    期初用django 开发应用的时候,完全是在urls.py 中硬编码配置地址,在views.py中HttpResponseRedirect()也是硬编码转向地址,当然在template 中也是一样了, ...

  9. 修改最大打开文件数和最大proc数量

    1.vim /etc/profile  增加 ulimit -n 10240 ulimit -u 10240 2.修改/etc/security/limits.conf *      soft     ...

  10. startssl 申请证书,并在Nginx, apache, Tomcat上使用

    tomcat: http://blog.csdn.net/buyaore_wo/article/details/5771470 apache: http://blog.mowd.tw/index.ph ...