android 之 Crash信息的持久化处理
需求: 持久化运行时异常的信息
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信息的持久化处理的更多相关文章
- 获取Android崩溃crash信息并写入日志发送邮件
一.实现Thread.UncaughtExceptionHandlerUnChecked异常发生时,由于没有相应的try…catch处理该异常对象,所以Java运行环境将会终止,程序将退出,也就是我们 ...
- 保留全部Android crash信息
保留全部Android crash信息 framework/base/core/java/com/android/internal/os/RuntimeInit.java 又一次以下这个函数,增加自己 ...
- Android怎样捕获应用的crash信息
转载请注明出处:http://blog.csdn.net/fishle123/article/details/50823358 我们的应用不可避免的会发生crash,假设是在调试阶段,我们能够使用Lo ...
- Android程序crash处理
Android程序crash处理 时间 2014-11-24 13:45:37 CSDN博客 原文 http://blog.csdn.net/allen315410/article/details ...
- Android程序Crash时的异常上报
转载请注明来源:http://blog.csdn.net/singwhatiwanna/article/details/17289479 前言 大家都知道,android应用不可避免的会发生crash ...
- Android Native crash日志分析
在Android应用crash的类型中,native类型crash应该是比较难的一种了,因为大家接触的少,然后相对也要多转几道工序,所有大部分对这个都比较生疏.虽然相关文章也有很多了,但是我在刚开始学 ...
- 使用CrashHandler获取应用crash信息
Android应用不可避免会发生crash,也称之为崩溃.发生原因可能是由于Android系统底层的bug,也可能是由于不充分的机型适配或者是糟糕的网络情况.当crash发生时,系统会kill掉正 ...
- I.MX6 android 获取framebuffer信息
/******************************************************************************** * I.MX6 android 获取 ...
- Android内存等信息
1. Linux中proc目录下文件详解 http://wenku.baidu.com/view/2ce89f00a6c30c2259019ef1.html 2. Android系统/proc目录详解 ...
随机推荐
- C#资源释放
转自:http://www.cnblogs.com/psunny/archive/2009/07/07/1518812.html 深刻理解C#中资源释放 今天我的一个朋友看到我写的那篇<C#中用 ...
- zabbix监控MySQL
通过使用mysql_performance_monitor软件包实现zabbix对mysql的监控. 1.安装依赖软件.yum install perl-File-Which perl-libwww- ...
- nginx学习
nginx源码学习是一个痛苦又快乐的过程,下面列出了一些nginx的学习资源. 首先要做的当然是下载一份nginx源码,可以从nginx官方网站下载一份最新的. 看了nginx源码,发现这是一份完全没 ...
- 第一篇 Integration Services:SSIS是什么
本篇文章是Integration Services系列的第一篇,详细内容请参考原文. Integration Services是一种在SQL Server中最受欢迎的子系统.允许你在各种数据源之间提取 ...
- cookie&session&servletContext
一.cookie VS session 1)应用场景 cookie可以用于: 记录用户上次登录的时间 记住用户名和密码 session可以用于: 防止非法登录(即直接跳转到本来需登录验证方可登录的页面 ...
- canvas 基础知识整理(一)
canvas这个 HTML 元素是为了客户端矢量图形而设计的.它自己没有行为,但却把一个绘图 API 展现给客户端 JavaScript 以使脚本能够把想绘制的东西都绘制到一块画布上. html的基本 ...
- 深入理解JAVA I/O系列六:Linux中的IO模型
IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大致描述了数据从外部磁盘向运行中程序的内存中移动的过程. 用户空间.内核空间 现在操作系统都是采用虚拟存储器, ...
- HTML--表单,图片热点,网页划区和拼接
一.图片热点 规划出图片上的一个区域,可以做出超链接,直接点击图片区域就可以完成跳转的效果. 示例: <img src="/ usemap="longzhu"> ...
- 创建Java类并实例化深入理解
package com.sanguosha.java; import java.util.Scanner;//导入包 public class TestPerson { public static v ...
- 前端新手分析 AJAX执行顺序,数据走向
我是一名前端的newer 在刚学习AJAX和eJS的时候,对于顺序上面有很大迷惑,现在稍微清楚了一点, 理解不对的地方,还请各位大牛帮助给我指导一下. 总的 服务器和客户端的顺序 一. 除了必要的 ...