直接使用的类,下面代码:
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
public class CrashHandler implements UncaughtExceptionHandler{
//系统默认的UncaughtException处理类
private Thread.UncaughtExceptionHandler mDefaultHandler;
//CrashHandler实例
private static CrashHandler instance = new CrashHandler();
//程序的Context对象
//用来存储设备信息和异常信息
private Map<String, String> infos = new HashMap<String, String>();
//用于格式化日期,作为日志文件名的一部分
private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
/** 保证只有一个CrashHandler实例 */
private CrashHandler() {
}
/** 获取CrashHandler实例 ,单例模式 */
public static CrashHandler getInstance() {
return instance;
}
/**
* 初始化
*
* @param context
*/
public void init(Context 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("CrashHandler", "error : ", e);
}
//退出程序
android.os.Process.killProcess(android.os.Process.myPid());
}
}
/**
* 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
//保存日志文件
saveCrashInfo2File(ex);
return true;
}
/**
* 保存错误信息到文件中
*
* @param ex
* @return 保存错误信息到文件中 返回文件名称,
*/
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");
}
Writer writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
ex.printStackTrace(printWriter);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(printWriter);
cause = cause.getCause();
}
printWriter.close();
String result = writer.toString();
sb.append(result);
try {
long timestamp = System.currentTimeMillis();
String time = formatter.format(new Date());
String fileName = "crash-" + time + "-" + timestamp + ".log";
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
String path = Environment.getExternalStorageDirectory().getPath()+"/crash/";
File dir = new File(path);
if (!dir.exists()) {
dir.mkdirs();
}
FileOutputStream fos = new FileOutputStream(path + fileName);
fos.write(sb.toString().getBytes());
fos.close();
}
return fileName;
} catch (Exception e) {
Log.e("CrashHandler", "an error occured while writing file...", e);
}
return null;
}
}
------------
需要 初始化:通过getInstance()获取实例,然后调用init(context);进行初始化
其中log输出位置是sdcard下的crash文件夹,名字是”crash-” + time + “-” + timestamp + “.log”的文件。
上面代码中没有对程序的崩溃进行处理,比如重开之类的,只是记录了下崩溃的原因,然后让程序挂掉了。如果想重开程序,或者其他的处理,可以在下面方法内实现:
@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("CrashHandler", "error : ", e);
}
//退出程序
//替换成需要做的操作
android.os.Process.killProcess(android.os.Process.myPid());
}
}
·····崩溃的日志已拿到,可以在开启app的时候遍历文件夹/crash,把文件夹下的文件上传到服务器,这样可以收集错误崩溃信息了。
由于做的项目是定制的rom,所以没获取系统的版本等等信息,网上有一些教程获取到了手机的各种信息,包括手机型号,系统版本等等,有需要可以自己动手查找。