主要类别:

package com.example.callstatus;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast; /**
* 捕获android程序崩溃日志<br>
* UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序.
*
* @author PMTOAM
*
*/
@SuppressLint("SimpleDateFormat")
public class CrashHandler implements UncaughtExceptionHandler
{ public static final String TAG = CrashHandler.class.getCanonicalName(); // 系统默认的UncaughtException处理类
private Thread.UncaughtExceptionHandler mDefaultHandler;
// CrashHandler实例
private static CrashHandler INSTANCE = new CrashHandler();
// 程序的Context对象
private Context mContext;
// 用来存储设备信息和异常信息
private Map<String, String> infos = new HashMap<String, String>(); // 用于格式化日期,作为日志文件名称的一部分
private DateFormat formatter = new SimpleDateFormat("yyyyMMdd_HHmmss"); /**
* 保证仅仅有一个实例
*/
private CrashHandler()
{
} /**
* 获取实例 ,单例模式
*/
public static CrashHandler getInstance()
{
return INSTANCE;
} /**
* 初始化
*
* @param context
*/
public void init(Context context)
{
mContext = context;
// 获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 设置该CrashHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
} /**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex)
{
if (!handleException(ex) && mDefaultHandler != null)
{
// 假设用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
}
else
{
try
{
Thread.sleep(3000);
}
catch (InterruptedException e)
{
Log.e(TAG, "error : ", e);
} // 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
} /**
* 自己定义错误处理,收集错误信息 发送错误报告等操作均在此完毕.
*
* @param ex
* @return true:假设处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex)
{
if (ex == null)
{
return false;
} // 使用Toast来显示异常信息
new Thread()
{
@Override
public void run()
{
Looper.prepare();
Toast.makeText(mContext, "非常抱歉。程序出现异常。 ", Toast.LENGTH_LONG)
.show();
Looper.loop();
}
}.start(); // 收集设备參数信息
collectDeviceInfo(mContext); // 保存日志文件
String str = saveCrashInfo2File(ex);
Log.e(TAG, str); return false;
} /**
* 收集设备參数信息
*
* @param ctx
*/
public void collectDeviceInfo(Context ctx)
{
try
{
PackageManager pm = ctx.getPackageManager();
PackageInfo pi = pm.getPackageInfo(ctx.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);
} }
catch (NameNotFoundException e)
{
Log.e(TAG, "an error occured when collect package info", e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields)
{
try
{
field.setAccessible(true);
infos.put(field.getName(), field.get(null).toString());
Log.d(TAG, field.getName() + " : " + field.get(null));
}
catch (Exception e)
{
Log.e(TAG, "an error occured when collect crash info", e);
}
}
} /**
* 保存错误信息到文件里
*
* @param ex
* @return 返回文件名称称,便于将文件传送到server
*/
private String saveCrashInfo2File(Throwable ex)
{ StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : infos.entrySet())
{
String key = entry.getKey();
String value = entry.getValue();
sb.append("[" + key + ", " + value + "]\n");
} sb.append("\n" + getStackTraceString(ex)); try
{
String time = formatter.format(new Date()); TelephonyManager mTelephonyMgr = (TelephonyManager) mContext
.getSystemService(Context.TELEPHONY_SERVICE);
String imei = mTelephonyMgr.getDeviceId();
if (TextUtils.isEmpty(imei))
{
imei = "unknownimei";
} String fileName = "CRS_" + time + "_" + imei + ".txt"; File sdDir = null; if (Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED))
sdDir = Environment.getExternalStorageDirectory(); File cacheDir = new File(sdDir + File.separator + "dPhoneLog");
if (!cacheDir.exists())
cacheDir.mkdir(); File filePath = new File(cacheDir + File.separator + fileName); FileOutputStream fos = new FileOutputStream(filePath);
fos.write(sb.toString().getBytes());
fos.close(); return fileName;
}
catch (Exception e)
{
Log.e(TAG, "an error occured while writing file...", e);
}
return null;
} /**
* 获取捕捉到的异常的字符串
*/
public static String getStackTraceString(Throwable tr)
{
if (tr == null)
{
return "";
} Throwable t = tr;
while (t != null)
{
if (t instanceof UnknownHostException)
{
return "";
}
t = t.getCause();
} StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
tr.printStackTrace(pw);
return sw.toString();
}
}

用法:

package com.example.callstatus;

import android.app.Application;

public class MyApplication extends Application
{
@Override
public void onCreate()
{
super.onCreate(); CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext());
}
}

所需权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

版权声明:本文博主原创文章。博客,未经同意不得转载。

捕android程序崩溃日志的更多相关文章

  1. 保存android程序崩溃日志到SD卡

    private boolean writeToSDCard(Throwable ex) { boolean isDealing = false; if (Environment.getExternal ...

  2. android 程序崩溃crash日志的捕捉

    android 程序崩溃crash日志的捕捉 之前在项目开发过程中,一直会遇到程序崩溃了,但是测试組的哥哥们又没及时的导出日志.... 后来在诳群的时候听别人说起,腾讯有那么一个叫bugly的东西 将 ...

  3. Android程序崩溃异常收集框架

    最近在写Android程序崩溃异常处理,完成之后,稍加封装与大家分享. 我的思路是这样的,在程序崩溃之后,将异常信息保存到一个日志文件中,然后对该文件进行处理,比如发送到邮箱,或发送到服务器. 所以, ...

  4. iOS - 捕获应用程序崩溃日志

    作为一名iOS移动应用开发者,为了确保你的应用程序正确无误,在将应用程序提交到应用商店之前,你必定会进行大量的测试工作:而且在你测试的过程中应用程序运行的很好,但是在应用商店上线之后,还是有用户抱怨应 ...

  5. iOS 中捕获程序崩溃日志

    iOS 中捕获程序崩溃日志 (2014-04-22 17:35:59) 转载▼     iOS开发中遇到程序崩溃是很正常的事情,如何在程序崩溃时捕获到异常信息并通知开发者,是大多数软件都选择的方法.下 ...

  6. android app崩溃日志收集以及上传

    源代码获取请到github:https://github.com/DrJia/AndroidLogCollector 已经做成sdk的形式,源代码已公开,源代码看不懂的请自行google. 假设想定制 ...

  7. Android 应用程序崩溃日志捕捉

    程序崩溃是应用迭代中不可避免的问题,即使有着5年或者10年经验的程序猿也无法完全保证自己的代码没有任何的bug导致崩溃,现在有一些第三方平台可以帮助我们搜集应用程序的崩溃,比如友盟,详情如下图 虽然能 ...

  8. Android 程序崩溃后的处理

    在应用发布以后,由于安卓机型的千差万别 ,可能会出现各种各样的问题,这时候如果我们可以将这些信息收集起来,并进行修改就很不错了.下面就来讨论一下怎么处理程序崩溃以后,错误信息的手机. Java中已经提 ...

  9. iOS开发-捕获程序崩溃日志

    iOS开发中遇到程序崩溃是很正常的事情,如何在程序崩溃时捕获到异常信息并通知开发者,是大多数软件都选择的方法.下面就介绍如何在iOS中实现: 1. 在程序启动时加上一个异常捕获监听,用来处理程序崩溃时 ...

随机推荐

  1. 学习springMVC实例1——配置和跳转到HelloWorld

    本文让大家迅速掌握springMVC的使用方法,以最简单的方式理解此框架 一.用eclipse新建一个web项目,命名为springMVC1,tomcat的端口号为9090 二.在WEB-INF目录下 ...

  2. vs2012快捷键

    (1)自己整理的使用频率最高的快捷键(建议大家亲身体验一下!这样才会在潜移默化中运用得到!) (这里省去了很多大家闭上眼都会操作的什么Ctrl+S 等等操作 给出的大多是不常用但是很有用的快捷键组合! ...

  3. Object Storage(Swift)安装过程——Havana

    自从看了Havana安装文档有关Swift的安装一节,发现H版的安装过程与以前还是有些差别的.不过大致过程还是那些.下面简单介绍下我们安装的过程吧,具体请参考官方文档http://docs.opens ...

  4. 理解javascript之 对象

    大纲: 1.介绍attribute property的异同,翻译自http://javascript.info/tutorial/attributes-and-custom-properties#pr ...

  5. (转)Android Studio系列教程一下载与安装 背景Android Studio VS Eclipse准备下载创建HelloWorld项目

    背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Goo ...

  6. js Math函数

    1.丢弃小数部分,保留整数部分parseInt(5/2) 2.向上取整,有小数就整数部分加1 Math.ceil(5/2) 3,四舍五入. Math.round(5/2) 4,向下取整 Math.fl ...

  7. Html5 Canvas学习

    canvas: 首先在html页面中加入canvas标签 <canvas id="canvas" width="1024" height="74 ...

  8. 网易DBA私享会分享会笔记2

    mysql索引与查询优化什么是索引?索引其实是一个目录.通过各种数据结构实现,是(值=>行位置)的映射 索引的作用:1.提高访问速度2.实现主键.唯一键逻辑 索引使用场景数据量特别大的时候,进行 ...

  9. web ajax跨域问题解决方案

      jsonpHandler({ "code": "aaa", "price": 1780, "tickets": 5 ...

  10. JS 输出与变量

    1. JS的输出 innerHTML: <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...