直接贴完整代码,详细介绍,里面有做介绍
public class ExceptionCrashHanlder implements UncaughtExceptionHandler {
private static final String TAG = ExceptionCrashHanlder.class.getSimpleName();
private static ExceptionCrashHanlder instance;
private Context mContext;
private UncaughtExceptionHandler mDefaultException;
/**
* 双重校验锁,减少并发
*/
public static ExceptionCrashHanlder getInstance() {
if (instance == null) {
synchronized (ExceptionCrashHanlder.class) {
if (instance == null) {
instance = new ExceptionCrashHanlder();
}
}
}
return instance;
}
public void init(Context context) {
mContext = context;
//设置全局变量是本类
Thread.currentThread().setUncaughtExceptionHandler(this);
//获取系统默认的
mDefaultException = Thread.currentThread().getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread t, Throwable e) {
//全局异常捕获处理
Log.e(TAG, "捕获异常了");
//1.奔溃的详细信息
//2.应用信息 包名 版本号
//3.手机信息
//4.上传问题,不在这里
//写入到本地文件 ex 当前版本 手机信息
String crashFileName = saveInfoToSD(e);
//缓存崩溃日志文件
cacheCrashFile(crashFileName);
//让默认系统处理
mDefaultException.uncaughtException(t, e);
}
/**
* 缓存文件
*/
private void cacheCrashFile(String fileName) {
SharedPreferences sp = mContext.getSharedPreferences("crash", Context.MODE_PRIVATE);
sp.edit().putString("CRASH_FILE_NAME", fileName).commit();
}
/**
* 获取本地文件
*/
public File getCrashFile() {
String crashFileName = mContext.getSharedPreferences("crash",
Context.MODE_PRIVATE).getString("CRASH_FILE_NAME", "");
return new File(crashFileName);
}
/**
* 保存获取的 软件信息,设备信息和出错信息保存在SDcard中
*/
private String saveInfoToSD(Throwable e) {
String fileName = null;
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> entry : obtainSimpleInfo(mContext).entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
sb.append(key).append(" = ").append(value).append("\n");
}
sb.append(obtainExceptionInfo(e));
//将sb拼起来的保存一个文件
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
/**
* 比如说要在temp目录下建立一个test.txt文件,在Windows下应该这么写:
File file1 = new File ("C:\tmp\test.txt");
在Linux下则是这样的:
File file2 = new File ("/tmp/test.txt");
如果要考虑跨平台,则最好是这么写:
File myFile = new File("C:" + File.separator + "tmp" + File.separator, "test.txt");
*/
File file = new File(mContext.getFilesDir() + File.separator + "crash"
+ File.separator);
//先删除之前的异常信息
if (file.exists()) {
deleteDir(file);
}
//再重新创建新的文件夹
if (!file.exists()) {
file.mkdir();
}
try {
fileName = file.toString() + File.separator + getAssignTime("yyyy_MM_dd_HH_mm") + ".txt";
FileOutputStream fos = new FileOutputStream(fileName);
fos.write(sb.toString().getBytes());
fos.flush();//缓冲区的数据强行输出
fos.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
return fileName;
}
/**
* 获取时间
*/
private String getAssignTime(String dateFormat) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
DateFormat format = new SimpleDateFormat(dateFormat);
long currentTime = System.currentTimeMillis();
return format.format(currentTime);
}
return null;
}
/**
* 递归删除目录下的所有文件及子目录下所有文件
*/
private boolean deleteDir(File file) {
if (file.isDirectory()) {
String[] list = file.list();
// 递归删除目录中的子目录下
for (String s : list) {
boolean success = deleteDir(new File(file, s));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return file.delete();
}
/**
* 获取系统未捕捉的错误信息
*/
private String obtainExceptionInfo(Throwable e) {
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
e.printStackTrace(printWriter);
printWriter.close();
return stringWriter.toString();
}
/**
* 获取一些简单的信息,软件版本,手机版本,型号等信息存放在HashMap中
*/
private HashMap<String, String> obtainSimpleInfo(Context context) {
HashMap<String, String> map = new HashMap<>();
PackageManager manager = context.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = manager.getPackageInfo(context.getPackageName()
, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
map.put("versionName", packageInfo.versionName);
map.put("versionCode", "" + packageInfo.versionCode);
map.put("MODEL", Build.MODEL);//版本
map.put("SDK_INT", Build.VERSION.SDK_INT + "");//版本号
map.put("PRODUCT", Build.PRODUCT); //手机制造商
map.put("MOBLE_INFO", getMobileInfo()); //手机信息
return map;
}
//获取手机信息
public String getMobileInfo() {
StringBuffer sb = new StringBuffer();
try {
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);//可以访问所有的信息
String name = field.getName();
String value = field.get(null).toString();
sb.append(name + "=" + value);
sb.append("\n");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return sb.toString();
}
}
测试
try {
File file = ExceptionCrashHanlder.getInstance().getCrashFile();
if (file.exists()) {
InputStreamReader reader = new InputStreamReader(new FileInputStream(file));
int len = -1;
char[] buf = new char[1024];
while ((len = reader.read(buf)) != -1) {
String s = new String(buf);
Log.e("TAG", s);
//上传服务器这里就不做了
}
}
} catch (Exception e) {
e.printStackTrace();
}
// int i = 5 / 0;