定義CrashLog文件:若是有存儲器,則將文件保存在存儲器下。不然保存在data目錄下。存儲器不必定是SD卡,也多是mount出來的一塊存儲空間(不是內存)。好比,小米3就沒有SD卡。java
public class CrashLog { private static Context mContext; public static final String DIR_FOR_APP = "myApp"; public static final String FILE_NAME_FOR_CRASH__LOG = "crash.txt"; public static void setContext( Context aContext ) { mContext = aContext.getApplicationContext(); } public static void writeLog(String log) throws Exception { File dir = createFileDir(DIR_FOR_APP); File file = new File(dir.getPath(), FILE_NAME_FOR_CRASH__LOG); if(!file.exists()){ file.createNewFile(); } StringBuffer orgStr = new StringBuffer(); FileReader fr = new FileReader(file); int ch = 0; while((ch = fr.read()) != -1) { orgStr.append((char)ch); } fr.close(); Calendar c = Calendar.getInstance(); String time = String.format("%2d:", c.get(Calendar.HOUR))+ String.format("%2d:", c.get(Calendar.MINUTE))+ String.format("%2d", c.get(Calendar.SECOND))+" "; String str = orgStr.toString() + "\r\n" + time + log + "\r\n"; FileWriter fw = new FileWriter(file); fw.write(str); fw.close(); } public static void clearLog(){ String dirPath = getDirPath(DIR_FOR_APP); if( dirPath != null ) { File file = new File(FILE_NAME_FOR_CRASH__LOG); if(file.exists()){ file.delete(); } } } public static String getDirPath(String dirName){ String filePath = null; String state = Environment.getExternalStorageState(); if (state.equals(Environment.MEDIA_MOUNTED)) { // 若是有存儲器,則返回存儲器的路徑 filePath = Environment.getExternalStorageDirectory() + File.separator + dirName; } else {// 不然返回data目錄的路徑 filePath = mContext.getCacheDir().getPath() + File.separator + dirName; } return filePath; } public static File createFileDir(String dirName) { String filePath = getDirPath(dirName); if( filePath == null ) { return null; } File destDir = new File(filePath); if (!destDir.exists()) { destDir.mkdirs(); } return destDir; } }
2. 定義CrashHandler異常捕獲類:當程序拋出異常後,由CrashHandler先捕獲。將異常堆棧信息和手機系統信息打印到手機制定位置的log文件後,退出。android
public class CrashHandler implements UncaughtExceptionHandler { private Context mContext; private static CrashHandler mInstance = null; // 系統默認的異常處理(默認狀況下,系統會終止當前的異常程序) private UncaughtExceptionHandler mDefaultCrashHandler; private CrashHandler(Context c) { // 獲取系統默認的異常處理器 mDefaultCrashHandler = Thread .getDefaultUncaughtExceptionHandler(); // 將當前實例設爲系統默認的異常處理器 Thread.setDefaultUncaughtExceptionHandler(this); // 獲取Context,方便內部使用 mContext = c.getApplicationContext(); } public synchronized static CrashHandler create(Context cxt) { if (mInstance == null) { mInstance = new CrashHandler(cxt); } return mInstance; } /** * 當UncaughtException發生時會回調該函數來處理 */ @Override public void uncaughtException(Thread thread, Throwable ex) { // TODO Auto-generated method stub StringBuffer logInfo = new StringBuffer(); logInfo.append("Exception: "); logInfo.append(ex.getMessage()); logInfo.append("\r\n"); logInfo.append(getStackMsg(ex)); logInfo.append("Phone informations:"); logInfo.append("\r\n"); try { logInfo.append(getPhoneInfo()); // 導出異常信息到存儲器中 CrashLog.writeLog(logInfo.toString()); } catch (Exception e) { //忽略異常 } finally { // 若是系統提供了默認的異常處理器,則交給系統去結束程序, if (mDefaultCrashHandler != null) { mDefaultCrashHandler.uncaughtException(thread, ex); } else { MyApplication.getInstance().exit(); } } } private static String getStackMsg(Throwable e) { StringBuffer sb = new StringBuffer(); StackTraceElement[] stackArray = e.getStackTrace(); for (int i = 0; i < stackArray.length; i++) { StackTraceElement element = stackArray[i]; sb.append(element.toString() + "\r\n"); } return sb.toString(); } private String getPhoneInfo() throws NameNotFoundException { StringBuffer info = new StringBuffer(); // 應用的版本號 PackageManager pm = mContext.getPackageManager(); PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES); info.append("App Version Name: "); info.append(pi.versionName); info.append("\r\n"); // android版本號 info.append("OS Version: "); info.append(Build.VERSION.RELEASE); info.append("_"); info.append(Build.VERSION.SDK_INT); info.append("\r\n"); // 手機制造商 info.append("Vendor: "); info.append(Build.MANUFACTURER); info.append("\r\n"); // 手機型號 info.append("Model: "); info.append(Build.MODEL); info.append("\r\n"); // cpu架構 info.append("CPU ABI: "); info.append(Build.CPU_ABI); info.append("\r\n"); return info.toString(); } }
3. 自定義Application類,初始化CrashLog和CrashHandler,並提供徹底退出應用的接口exit()。架構
public class MyApplication extends Application{ // 單例模式 private static MyApplication mAppInstance; // Activity容器 private List<Activity> mActivityList = new LinkedList<Activity>(); public MyApplication(){ } public static MyApplication getInstance() { if( mAppInstance == null ) { mAppInstance = new MyApplication(); } return mAppInstance; } // 每新建一個Activity,都要添加到容器中 public void addActivity(Activity a){ mActivityList.add(a); } // 遍歷容器中全部Activity並finish public void exit(){ for (Activity activity : mActivityList) { activity.finish(); } System.exit(0); } @Override public void onCreate() { super.onCreate(); CrashLog.setContext(this); CrashHandler.create(this); } }