package com.fanxin.huangfangyi.main.utils; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Environment; import android.os.Process; import android.util.Log; import com.alibaba.fastjson.JSONObject; import com.fanxin.huangfangyi.main.FXConstant; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FilenameFilter; import java.lang.Thread.UncaughtExceptionHandler; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.TreeSet; /** * Crash * 异常拦截器 * create by Zhiqiang_H 2016-03-23 */ public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; /** 是否开启日志输出,在Debug状态下开启, * 在Release状态下关闭以提示程序性能 * */ public static final boolean DEBUG = true; private static CrashHandler instance; private Context context; private String errorLogDir = null; private SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); /** 错误报告文件的扩展名 */ private static final String CRASH_REPORTER_EXTENSION = ".txt"; private final int expirationDate = 7;//设置过期时间(单位:天) private File file;//保存的文件路径 private CrashHandler(){ } public synchronized static CrashHandler getInstance(){ if(instance == null){ instance = new CrashHandler(); } return instance; } public void init(Context context){ init(context,getDefaultSaveRootPath(context)); } public void init(Context context, String errorLogDir){ this.context = context; this.errorLogDir = errorLogDir; Thread.setDefaultUncaughtExceptionHandler(this); //删除过期文件 new Thread(new Runnable() { @Override public void run() { deleteExpirationFile(); } }).start(); } @Override public void uncaughtException(Thread thread, Throwable ex) { if(ex != null) { //收集设备信息 disposeThrowable(ex); ex.printStackTrace(); } } private void disposeThrowable(Throwable ex){ getInfo(); String mtype = android.os.Build.MODEL; // 手机型号 String mtyb= android.os.Build.BRAND;//手机品牌 String cpuAbi = android.os.Build.CPU_ABI;//cpu架构 String sdk = android.os.Build.VERSION.SDK;//sdk版本号 String release = android.os.Build.VERSION.RELEASE;//依赖的系统版本号 String manufacturer = android.os.Build.MANUFACTURER;//手机品牌 StringBuffer sb = new StringBuffer(); sb.append("手机系统信息:"+"\n"+"手机品牌:"+mtyb+"\n" +"手机型号:"+mtype+"\n"+"制造商:"+manufacturer+"\n"+"手机系统版本号:"+release+"\n"+"系统SDK版本号:"+sdk+"\n"+"cpu架构:"+cpuAbi+"\n"); sb.append("错误信息:"+"\n"+ex.toString()+"\n"); sb.append("错误所在:"+"\n"); StackTraceElement[] steArray = ex.getStackTrace(); for(StackTraceElement ste : steArray){ sb.append("System.err at " + ste.getClassName() + "." + ste.getMethodName() + "(" + ste.getFileName() + ":" + ste.getLineNumber() + ")\n"); } if(errorLogDir != null){ try { file = new File(errorLogDir+File.separator + "Error" + File.separator+ sdf.format(System.currentTimeMillis()) + CRASH_REPORTER_EXTENSION); if(!file.exists()){ file.getParentFile().mkdirs(); file.createNewFile(); printLog(TAG,"chuangjianfile"); } FileOutputStream fos = new FileOutputStream(file); fos.write(sb.toString().getBytes("utf-8")); fos.flush(); fos.close(); printLog(TAG,"xie如成功"); fos = null; }catch (Exception e){ e.printStackTrace(); printLog(TAG,"errorLogDir:"+errorLogDir +"Exception:" +e.getMessage()); } } Process.killProcess(Process.myPid()); System.exit(10); } /** * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告 */ public void sendPreviousReportsToServer() { Log.d(TAG,"走了发送异常报告"); sendCrashReportsToServer(); } /** * 把错误报告发送给服务器,包含新产生的和以前没发送的. */ private void sendCrashReportsToServer() { String[] crFiles = getCrashReportFiles(); if (crFiles != null && crFiles.length > 0) { TreeSet<String> sortedFiles = new TreeSet<String>(); sortedFiles.addAll(Arrays.asList(crFiles)); for (String fileName : sortedFiles) { File cr = new File(errorLogDir+File.separator + "Error", fileName); printLog(TAG,"fileName:"+fileName); postReport(cr); cr.delete();// 删除已发送的报告 } } } private void postReport(File file) { List<Param> params = new ArrayList<>(); params.add(new Param("crash","crash")); List<File> files = new ArrayList<File>(); if (file.exists()){ files.add(file); } Log.d(TAG,"走了发送异常报告:"+file.toString()); // TODO 发送错误报告到服务器 new OKHttpUtils(context).post(params, files, FXConstant.HOST, new OKHttpUtils.HttpCallBack() { @Override public void onResponse(JSONObject jsonObject) { printLog(TAG,"走了发送异常报告:"+jsonObject); printLog(TAG,"crashjsonObject:"+jsonObject); } @Override public void onFailure(String errorMsg) { printLog(TAG,"crasherrorMsg:"+errorMsg); printLog(TAG,"没走:"+errorMsg); } }); } /** * 获取错误报告文件名 * @return */ private String[] getCrashReportFiles() { File filesDir = new File(errorLogDir+File.separator + "Error"); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(CRASH_REPORTER_EXTENSION); } }; return filesDir.list(filter); } private void deleteExpirationFile(){ if(errorLogDir == null){ return; } long expirationTime = expirationDate * 24 * 3600 * 1000; long nowTime = System.currentTimeMillis(); List<File> deleteList = new ArrayList<File>(); File dir = new File(errorLogDir); if(dir.isDirectory()){ File[] files = dir.listFiles(); for(File f : files){ if(f.exists()){ long time = f.lastModified(); if(nowTime - time >= expirationTime){ deleteList.add(f); } } } for(File f : deleteList){ f.delete(); } } } /** * 获取IMEI号,IESI号,手机型号 */ private String getInfo() { String mtype = android.os.Build.MODEL; // 手机型号 String mtyb= android.os.Build.BRAND;//手机品牌 String cpuAbi = android.os.Build.CPU_ABI;//cpu架构 String sdk = android.os.Build.VERSION.SDK;//sdk版本号 String release = android.os.Build.VERSION.RELEASE;//依赖的系统版本号 String device = android.os.Build.DEVICE;//设备 String manufacturer = android.os.Build.MANUFACTURER;//手机品牌 String mobileInfo = "手机品牌:"+mtyb+",手机型号:"+mtype+",cpu架构:"+cpuAbi+",系统SDK版本号:"+sdk+",手机系统版本号:"+release+",制造商:"+manufacturer; printLog(TAG,"mobile:"+mobileInfo); return mobileInfo; } /** * .获取手机MAC地址 * 只有手机开启wifi才能获取到mac地址 */ private String getMacAddress(Context context){ String result = ""; WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); result = wifiInfo.getMacAddress(); return result; } /** * 手机CPU信息 */ private String[] getCpuInfo() { String str1 = "/proc/cpuinfo"; String str2 = ""; String[] cpuInfo = {"", ""}; //1-cpu型号 //2-cpu频率 String[] arrayOfString; try { FileReader fr = new FileReader(str1); BufferedReader localBufferedReader = new BufferedReader(fr, 8192); str2 = localBufferedReader.readLine(); arrayOfString = str2.split("\\s+"); for (int i = 2; i < arrayOfString.length; i++) { cpuInfo[0] = cpuInfo[0] + arrayOfString[i] + " "; } str2 = localBufferedReader.readLine(); arrayOfString = str2.split("\\s+"); cpuInfo[1] += arrayOfString[2]; localBufferedReader.close(); } catch (Exception e) { } printLog(TAG, "cpuinfo:" + cpuInfo[0] + " " + cpuInfo[1]); return cpuInfo; } /** * 获取APP文件目录下的cache文件家 * @return */ private String getDefaultSaveRootPath(Context applicion) { if (applicion.getExternalCacheDir() == null) { return Environment.getDownloadCacheDirectory().getAbsolutePath(); } else { //noinspection ConstantConditions return applicion.getExternalCacheDir().getAbsolutePath(); } } private void printLog(String tag ,String logMessage){ if (DEBUG){ Log.d(tag,logMessage); } } }