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

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. pip使用国内镜像服务器

    国内在使用pip安装python组件时特别慢,最好是使用国内的镜像获取python组件.测试过几个镜像服务器,douban的速度相对较快和稳定,因此经常用它作为镜像. 具体的修改步骤在pip手册上有, ...

  2. jQuery基础修炼圣典—DOM篇(一)

    一.DOM节点的创建 1.创建节点及节点属性 通过JavaScript可以很方便的获取DOM节点,从而进行一系列的DOM操作.但实际上一般开发者都习惯性的先定义好HTML结构,但这样就非常不灵活了. ...

  3. 解决:CWnd::SetWindowText报Assertion failure

    参考资料: http://www.cnblogs.com/tiancun/p/3756581.html http://www.tc5u.com/mfc/2120698.htm http://forum ...

  4. ios添加方法快捷方式

  5. 微信的公众号unionid

    此外,由于开发者经常有需在多个平台(移动应用.网站.公众帐号)之间共通用户帐号,统一帐号体系的需求,微信开放平台(open.weixin.qq.com)提供了UnionID机制.开发者可通过OpenI ...

  6. linux:档案与档案系统的压缩、打包与备份

    压缩比:压缩后与压缩的档案锁占用的磁碟空间大小,就称之为压缩比 压缩技术: a.将没有使用到的空间丢出去,以让档案资料占用的空间变小 b.将重复的资料统计记录(比如100个1,不是真正的用100个元位 ...

  7. 理解MapReduce

    理解MapReduce Hadoop的MapReduce过程具有如下形式:           1) map: (K1, V1) => list(K2, V2)          2) redu ...

  8. java Servlet中的过滤器Filter

    web.xml中元素执行的顺序listener->filter->struts拦截器->servlet. 1.过滤器的概念 Java中的Filter 并不是一个标准的Servlet ...

  9. sublime text 快速补全

    sublime text 快速补全 关于补全,其实有很多,记录一些常用的在这里,忘记了可以查找 nav>ul>li    <nav>          <ul>  ...

  10. PHP 小谈静态用法

    1.静态的表现形式,在PHP中定义一个静态变量需要加入一个关键字——static,静态对象是属于类的,非静态对象是属于对象的 class Fenbi { public $changdu;//属于对象的 ...