package com.hjx.personalcenter.crash; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Environment; import android.util.Log; import com.hjx.personalcenter.util.MachineUtil; import org.json.JSONObject; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.lang.Thread.UncaughtExceptionHandler; import java.util.HashMap; import java.util.Map; /** * UncaughtException处理类,当程序发生Uncaught异常的时候,有该类来接管程序,并记录发送错误报告. * * @author user * */ public class CrashHandler implements UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; // CrashHandler实例 private static CrashHandler INSTANCE = null; // 程序的Context对象 private Context mContext = null; private ExceptionHandler exceptionH = null; private StringBuffer log; // 文件保存路径 public static final String LOG_DIR = Environment.getExternalStorageDirectory().toString()+"/hjx/log";; private static final String APP_NAME = "APP_NAME"; private static final String VERSION_NAME = "VERSION_NAME"; private static final String VERSION_CODE = "VERSION_CODE"; private static final String APP_MODLE = "APP_MODLE";// 手机型号 private static final String CRASH_TIME = "CRASH_TIME"; private static final String DEVICE_NUMBER = "DEVICE_NUMBER"; // private static final String IMSI_CODE = "IMSI_CODE"; // private static final String PHONE_NUMBER = "PHONE_NUMBER"; private static final String OS_VERSION = "OS_VERSION"; private static final String MAC_ADDRESS = "MAC_ADDRESS"; /** 保证只有一个CrashHandler实例 */ private CrashHandler() { } /** 获取CrashHandler实例 ,单例模式 */ public static synchronized CrashHandler getInstance() { if(INSTANCE == null){ INSTANCE = new CrashHandler(); } return INSTANCE; } public interface ExceptionHandler{ /** * * @param context * @param ex * @return 如果返回true消费这个throwable false不消费 */ public boolean handleCrash(Context context, Throwable ex); } public void registerHandler(ExceptionHandler handler){ this.exceptionH = handler; } /** * 初始化 * * @param context */ public void init(Context context) { mContext = context; log = new StringBuffer(); // 设置该CrashHandler为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 当UncaughtException发生时会转入该函数来处理 */ @Override public void uncaughtException(Thread thread, Throwable ex) { if (!handleException(ex)) { // 收集设备参数信息 collectDeviceInfo(mContext); // 保存日志文件 saveCrashInfo2File(ex); // 解析文件信息 //parseFile(path); // 上传日志文件 // try { // urlPostFile(path); // } catch (Exception e) { // e.printStackTrace(); // } // 退出程序 } log.setLength(0); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } /** * 应用程序自己处理未捕获的异常 * * @param ex * @return true: 如果返回true消耗这个throwable false不消耗 */ private boolean handleException(Throwable ex) { if (exceptionH == null) { return false; }else{ return exceptionH.handleCrash(mContext, ex); } } /** * 收集参数信息 * * @param ctx */ private void collectDeviceInfo(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_META_DATA); if (pi != null) { String appName = pi.applicationInfo.loadLabel(pm).toString(); String versionName = pi.versionName == null ? "null" : pi.versionName; String versionCode = pi.versionCode + ""; log.append("{\"").append(APP_NAME).append("\":\"") .append(appName).append("\",\"") .append(VERSION_NAME).append("\":\"") .append(versionName).append("\",\"") .append(OS_VERSION).append("\":\"") .append(Build.VERSION.RELEASE).append("\",\"") .append(VERSION_CODE).append("\":\"") .append(versionCode).append("\",\"") .append(APP_MODLE).append("\":\"") .append(Build.MODEL).append("\",\"") .append(CRASH_TIME).append("\":\"") .append(System.currentTimeMillis()).append("\""); } } catch (Exception e) { Log.e(TAG, "an error occured when collect package info", e); log.setLength(0); log.append("{\"").append(APP_NAME).append("\":\"") .append("unkown").append("\",\"") .append(VERSION_NAME).append("\":\"") .append("unkown").append("\",\"") .append(OS_VERSION).append("\":\"") .append(Build.VERSION.RELEASE).append("\",\"") .append(VERSION_CODE).append("\":\"") .append("unkown").append("\",\"") .append(APP_MODLE).append("\":\"") .append(Build.MODEL).append("\",\"") .append(CRASH_TIME).append("\":\"") .append(System.currentTimeMillis()).append("\""); } try { //common android os /* TelephonyManager mTm = (TelephonyManager)ctx.getSystemService(Context.TELEPHONY_SERVICE); String imei = mTm.getDeviceId(); String imsi = mTm.getSubscriberId(); String numer = mTm.getLine1Number(); // 手机号码,有的可得,有的不可得 if(mTm != null){ log.append(",\"").append(DEVICE_NUMBER).append("\":\"") .append(TextUtils.isEmpty(imei)?"unkown":imei).append("\",\"") .append(IMSI_CODE).append("\":\"") .append(TextUtils.isEmpty(imsi)?"unkown":imsi).append("\",\"") .append(PHONE_NUMBER).append("\":\"") .append(TextUtils.isEmpty(numer)?"unkown":numer).append("\"}"); } */ //hjx machine log.append(",\"").append(DEVICE_NUMBER).append("\":\"") .append(getCPUSerial(ctx)).append("\",\"") .append(MAC_ADDRESS).append("\":\"") .append(getMacAddress(ctx)).append("\"}"); } catch (Exception e) { /* * common android os log.append(",\"").append(DEVICE_NUMBER).append("\":\"") .append("unkown").append("\",\"") .append(IMSI_CODE).append("\":\"") .append("unkown").append("\",\"") .append(PHONE_NUMBER).append("\":\"") .append("unkown").append("\"}"); */ log.append(",\"").append(DEVICE_NUMBER).append("\":\"") .append("unkown").append("\",\"") .append(MAC_ADDRESS).append("\":\"") .append("unkown").append("\"}"); Log.e(TAG, "an error occured when collect package info", e); } } private String getCPUSerial(Context context) { return MachineUtil.getMachineCode(context); } private String getMacAddress(Context mContext){ String ret = null; try { WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); WifiInfo info = manager.getConnectionInfo(); ret = info.getMacAddress(); } catch (Exception e) { Log.e(TAG, "get wifi address wrong", e); } return ret; } /** * 保存错误信息到文件中 * * @param ex * @return 返回文件名称,便于将文件传送到服务器 */ private String saveCrashInfo2File(Throwable ex) { // SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); 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(); log.append("\n").append(result); try { // String name = mContext.getPackageName(); // String time = formatter.format(new Date()); String fileName = System.currentTimeMillis()+".log"; if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { File dir = new File(LOG_DIR); if (!dir.exists()) { dir.mkdirs(); } FileOutputStream fos = new FileOutputStream(LOG_DIR+"/" + fileName); fos.write(log.toString().getBytes()); fos.close(); } return fileName; } catch (Exception e) { Log.e(TAG, "an error occured while writing file...", e); } return null; } /** * 解析文件信息 * * @param filePath * @return 装有相关信息的map */ @Deprecated public Map parseFile(String filePath) { BufferedReader read = null; try { read = new BufferedReader(new FileReader(filePath)); String line = read.readLine(); JSONObject jsonObj = new JSONObject(line); Map map = new HashMap(); map.put(APP_NAME, jsonObj.optString(APP_NAME)); map.put(APP_MODLE, jsonObj.optString(APP_MODLE)); map.put(VERSION_NAME, jsonObj.optString(VERSION_NAME)); map.put(VERSION_CODE, jsonObj.optString(VERSION_CODE)); map.put(CRASH_TIME, jsonObj.optString(CRASH_TIME)); StringBuffer sb = new StringBuffer(); int readed = 0; char[] buf = new char[1024]; while((readed = read.read(buf))!=-1){ sb.append(buf,0,readed); } map.put("CONTENT", sb.toString()); return map; } catch (Exception e) { e.printStackTrace(); } finally{ try { if(read != null) read.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } }