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

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. C语言命名空间

    //首先要认识到命名空间的使用条件.#include <stdio.h> typedef struct A { int A; } A; typedef union B { int A; } ...

  2. MVC项目实践,在三层架构下实现SportsStore-08,部署到IIS服务器

    SportsStore是<精通ASP.NET MVC3框架(第三版)>中演示的MVC项目,在该项目中涵盖了MVC的众多方面,包括:使用DI容器.URL优化.导航.分页.购物车.订单.产品管 ...

  3. C# 实例化多线程组

    代码如下 //实例化线程组 Thread[] clientThreads = new Thread[numThread]; ; i < numThread; i++) { clientThrea ...

  4. [ROS] slam_gmapping

    slam_gmapping节点 1)slam_gmapping 节点在sensor_msgs/LaserScan消息内获取数据并建立地图 map(nav_msgs/OccupancyGrid).该地图 ...

  5. c# Task编程一个task抛出异常后怎么取消其他线程

    从MSDN的Forum上看到别人提供的解决方案,感觉还是比较靠谱,所以就保存下来. CancellationTokenSource cts = new CancellationTokenSource( ...

  6. tornado中使用Mako模版

    tornado是一个优秀的python的开源web 框架,框架本身的性能确实很好,但是他自带的模版只能说是一般般.关于tornado的详细信息可以直接到管网参考. http://www.tornado ...

  7. node.js中使用node-schedule实现定时任务

    摘要:有时我们需要在每天的固定时间执行某个脚本,或者在某个固定时间执行某个任务.NodeJS中的 node-schedule 可以很好的实现定时任务. 1.安装 npm install node-sc ...

  8. 传递闭包(Floyd+bellman-Fold POJ1932)

    传递闭包 在一个有向(无向)连通图中,如果节点i与k联通,k与j联通,则i和j联通,传递闭包就是把所有传递性的节点求出来,之后就知道了任意两个节点的连通性,只需枚举节点的联通情况即可,无需考虑最短路径 ...

  9. codeforces 520 Pangram

    http://codeforces.com/problemset/problem/520/A A. Pangram time limit per test 2 seconds memory limit ...

  10. [原创]java WEB学习笔记51:国际化 概述,API 之 locale类,dataFormat类,numberFormat类, MessageFormat类,ResourceBundle 类

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...