一、实现Thread.UncaughtExceptionHandler
UnChecked异常发生时,由于没有相应的try…catch处理该异常对象,所以Java运行环境将会终止,程序将退出,也就是我们所说的Crash。Java API提供了一个全局异常捕获处理器,Android应用在Java层捕获Crash依赖的就是Thread.UncaughtExceptionHandler处理器接口,通常我们只需实现这个接口,并重写其中的uncaughtException方法,在该方法中可以读取Crash的堆栈信息

public class CrashManager implements Thread.UncaughtExceptionHandler {

    private Thread.UncaughtExceptionHandler mDefaultHandler;
private Map<String, String> infos;
private MyApplication application;
private static SimpleDateFormat logfile = new SimpleDateFormat("yyyy-MM-dd");// 日志文件格式 public CrashManager(MyApplication application){
//获取系统默认的UncaughtExceptionHandler
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
this.application = application;
} private boolean handleException(final Throwable exc){
if (exc == null) {
return false;
}
new Thread(new Runnable() {
@Override
public void run() {
Looper.prepare();//准备
Log.i("Urmytch","崩溃正在写入日志");
flushBufferedUrlsAndReturn();
//处理崩溃
collectDeviceAndUserInfo(application);
writeCrash(exc);
Looper.loop();
}
}).start();
return true;
} /**
* 把未存盘的url和返回数据写入日志文件
*/
private void flushBufferedUrlsAndReturn(){
//TODO 可以在请求网络时把url和返回xml或json数据缓存在队列中,崩溃时先写入以便查明原因
} /**
* 采集设备和用户信息
* @param context 上下文
*/
private void collectDeviceAndUserInfo(Context context){
PackageManager pm = context.getPackageManager();
infos = new HashMap<String, String>();
try {
PackageInfo pi = pm.getPackageInfo(context.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);
infos.put("crashTime",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("Urmytch",e.getMessage());
}
Field[] fields = Build.class.getDeclaredFields();
try {
for (Field field : fields) {
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
}
} catch (IllegalAccessException e) {
Log.e("Urmytch",e.getMessage());
}
} /**
* 采集崩溃原因
* @param exc 异常
*/ private void writeCrash(Throwable exc){
StringBuffer sb = new StringBuffer();
sb.append("------------------crash----------------------");
sb.append("\r\n");
for (Map.Entry<String,String> entry : infos.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key+"="+value+"\r\n");
}
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
exc.printStackTrace(pw);
Throwable excCause = exc.getCause();
while (excCause != null) {
excCause.printStackTrace(pw);
excCause = excCause.getCause();
}
pw.close();
String result = writer.toString();
sb.append(result);
sb.append("\r\n");
sb.append("-------------------end-----------------------");
sb.append("\r\n");
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
{
String sdcardPath = Environment.getExternalStorageDirectory().getPath();
Log.i("路径:",""+Environment.getExternalStorageDirectory().getPath());
//String filePath = sdcardPath + "//Urmytch/crash/";
String filePath = sdcardPath + "//kantu/crash/";
writeLog(sb.toString(), filePath); }
}
/**
*
* @param log 文件内容
* @param name 文件路径
* @return 返回写入的文件路径
* 写入Log信息的方法,写入到SD卡里面
*/
private String writeLog(String log, String name)
{
Date nowtime = new Date();
String needWriteFiel = logfile.format(nowtime);
//String filename = name + "mycrash"+ ".log";
String filename = name + "mycrash"+ needWriteFiel+".txt";
File file =new File(filename);
if(!file.getParentFile().exists()){
Log.i("Urmytch","新建文件");
file.getParentFile().mkdirs();
}
if (file != null && file.exists() && file.length() + log.length() >= 64 * 1024) {
//控制日志文件大小
file.delete();
}
try
{
file.createNewFile();
FileWriter fw=new FileWriter(file,true);
BufferedWriter bw = new BufferedWriter(fw);
//写入相关Log到文件
bw.write(log);
bw.newLine();
bw.close();
fw.close();
//发送邮件
SendMailUtil.send(file,"changyiqiang123@126.com");
return filename;
}
catch(IOException e)
{
Log.w("Urmytch",e.getMessage());
return null;
} }
@Override
public void uncaughtException(Thread thread, Throwable exc) {
if(!handleException(exc) && mDefaultHandler != null){
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, exc);
Log.i("打印:","1111");
}else{
Log.i("打印:","222"); try{
Thread.sleep(2000);
}catch (InterruptedException e){
Log.w("Urmytch",e.getMessage());
}
Intent intent = new Intent(application.getApplicationContext(), LoginActivity.class);
PendingIntent restartIntent = PendingIntent.getActivity(application.getApplicationContext(), 0, intent, 0);
//退出程序
AlarmManager mgr = (AlarmManager)application.getSystemService(Context.ALARM_SERVICE);
//1秒后重启应用
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, restartIntent);
android.os.Process.killProcess(android.os.Process.myPid());
} ////这里可以上传异常信息到服务器,便于开发人员分析日志从而解决Bug
// uploadExceptionToServer();
} /**
* 将错误信息上传至服务器
*/
private void uploadExceptionToServer() {
File file = new File(Environment.getExternalStorageDirectory()+File.separator+"test.txt");
OutputStream os = null;
try {
os = new FileOutputStream(file);
String str = "hello world";
byte[] data = str.getBytes();
os.write(data);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if (os != null)os.close();
} catch (IOException e) {
}
}
SendMailUtil.send(file,"changyiqiang123@126.com");
} }

  

二、在Application中注册

public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
CrashManager crashHandler = new CrashManager(this);
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
}
}

最后权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  

  完成

参考于:https://blog.csdn.net/urmytch/article/details/53642945

获取Android崩溃crash信息并写入日志发送邮件的更多相关文章

  1. 获取 Android APP 版本信息工具类(转载)

    获取 Android APP 版本信息工具类 获取手机APP版本信息工具类 1.获取版本名称 2.获取版本号 3.获取App的名称 package com.mingyue.nanshuibeidiao ...

  2. 常用获取Android崩溃日志和IOS崩溃日志的几种方法

    一:前言 在日常测试app时,经常会遇到崩溃问题,测试快速抓取到崩溃日志可以有效方便开发进行定位,快速解决问题所在测试做到测试分析,定位是非常重要的,这也是判断一个测试能力指标的一大维度. 二:And ...

  3. android 之 Crash信息的持久化处理

    需求: 持久化运行时异常的信息 1.CrashHandler.java import android.content.Context; import android.content.pm.Packag ...

  4. 使用CrashHandler来获取应用的crash信息

    源码地址https://github.com/king1039/android-art-res/tree/master/Chapter_13/CrashTest/src/com/ryg/crashte ...

  5. Windows Phone & Windows App应用程序崩溃crash信息抓取方法

    最近有用户反馈,应用有崩溃的情况,可是本地调试却无法重现问题,理所当然的,我想到了微软的开发者仪表盘,可以查看一段时间内的carsh记录,不过仪表盘生成carsh记录不是实时的,而且生成的报告查看非常 ...

  6. 获取android手机联系人信息

    package com.yarin.android.Examples_04_04; import android.app.Activity; import android.database.Curso ...

  7. 获取Android系统应用信息

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  8. java--何时处理Exception(哪一个层级),包装的基础类处理任务尽可能简洁,写入日志,检查null等运行时异常

    1. 运行时异常和受检异常 2. 提前预防运行时异常.最常发生的是NPE,而检查NPE是程序员的基本职责.其他的,如除0等运行时异常的检查,需要程序员仔细检查,每个函数都得检查(除非可以确定不会有空指 ...

  9. (转)获取android手机内部存储空间和外部存储空间的参数 && 如何决定一个apk的安装位置

    转:http://blog.csdn.net/zhandoushi1982/article/details/8560233 获取android文件系统的信息,需要Environment类和StatFs ...

随机推荐

  1. 接口八问 & 接口测试质量评估标准

    接口八问 关于接口的具体信息,可以通过以下八个问题进行了解: 接口的请求地址? 接口的作用? 接口的请求方式? 接口是否是用户相关? 接口是否存在上送数据,上送数据是什么? 接口返回的报文头和编码? ...

  2. java中判断两个对象是否相等

    package ceshi.com.job; import java.util.ArrayList; import java.util.Arrays; import java.util.List; p ...

  3. 01-cmake语法-基本

    本系列随笔将结合 OpenCV 的 CMakeLists.txt 来讲解 cmake 的语法. 这一节,主要介绍一下cmake语法的基本语法. cmake语法的基本语法 # 执行 cmake . # ...

  4. TCP协议的粘包问题(八)

    一.什么是粘包 在socket缓冲区和数据的传递过程介绍中,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发送了多少次,都会尽可能多的接收数据.也就是说,read()/re ...

  5. Java中的 Invalid character constant(无效的字符常数)

    将双引号误写成单引号,会出现这个错误. 1 package dftpkg; 2 3 public class Test { 4 5 public static void main(String[] a ...

  6. NOI2016优秀的拆分

    一种想法是枚举分割位置, 然后考虑前面部分有多少种可行的AA拆分方式, 后面部分有多少种可行的BB拆分方式, 然后乘法原理即可 那么问题是如何快速求出合法方案 解法是首先枚举长度len, 然后将序列分 ...

  7. Linux性能优化实战学习笔记:第六讲

    一.环境准备 1.安装软件包 终端1 机器配置:2 CPU,8GB 内存 预先安装 docker.sysstat.perf等工具 [root@luoahong ~]# docker -v Docker ...

  8. MySQL实战45讲学习笔记:第二十四讲

    一.引子 在前面的文章中,我不止一次地和你提到了 binlog,大家知道 binlog 可以用来归档,也可以用来做主备同步,但它的内容是什么样的呢?为什么备库执行了 binlog 就可以跟主库保持一致 ...

  9. 《30天自制操作系统》笔记4 --- (Day2 下节)了解如何用汇编写操作系统中的HelloWorld

    关于上一节,我测试了发现3e.4c.4e都OK ,4b 4d 4f都进不去系统还把qemu卡死了. 50不会输出HelloWorld,可能需要hex偶数且在0x3e~4f区间吧.上节复制并运行命令如下 ...

  10. 大话设计模式Python实现-策略模式

    策略模式(Strategy Pattern):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 下面是一个商场活动的实现 #!/usr/bin/e ...