主要源碼:
package com.demo.uploaderrorinfofile.common;import java.io.File;import java.io.FileOutputStream;import java.io.PRintWriter;import java.lang.Thread.UncaughtExceptionHandler;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.commons.collections.MapUtils;import org.apache.commons.collections.map.CaseInsensitiveMap;import org.apache.commons.lang.StringUtils;import com.demo.uploaderrorinfofile.Utils.FileNameUtils;import com.demo.uploaderrorinfofile.Utils.FilePathUtils;import com.demo.uploaderrorinfofile.Utils.HttpClientUpLoadTask;import com.demo.uploaderrorinfofile.Utils.JsonUtils;import com.demo.uploaderrorinfofile.Utils.PackageManagerUtils;import android.content.Context;//import android.content.pm.PackageInfo;import android.text.format.DateFormat;import android.util.Log;/** * 在application中統一捕獲異常,保存到文件中上傳 * 自定義異常類實現UncaughtExceptionHandler接口,當某個頁面出現 * 異常就會調用uncaughtException這個方法,我們可以在這個方法中獲取 * 異常信息、時間等,然后將獲取到的信息發送到我們指定的服務器 */public class CrashHandler implements UncaughtExceptionHandler { private static final String logTag = CrashHandler.class.getSimpleName();// private PackageInfo packageInfo; /** 系統默認的UncaughtException處理類 */ private Thread.UncaughtExceptionHandler defaultHandler; /** CrashHandler實例 */ private static CrashHandler INSTANCE; /** 程序的Context對象 */ private Context context; /** 保證只有一個CrashHandler實例 */ private CrashHandler() {} /** 獲取CrashHandler實例 ,單例模式*/ public static CrashHandler getInstance() { if (INSTANCE == null) { INSTANCE = new CrashHandler(); } return INSTANCE; } /** * 初始化,注冊Context對象, * 獲取系統默認的UncaughtException處理器, * 設置該CrashHandler為程序的默認處理器 * * @param ctx */ public void register(Context ctx) { this.context = ctx; //獲取默認的handler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); //設置自己的handler Thread.setDefaultUncaughtExceptionHandler(this); } /** * 當UncaughtException發生時會轉入該函數來處理 */ @Override public void uncaughtException(Thread thread, Throwable ex) { Log.d(logTag, "Now enter CrashHandler. In somewhere occur error. I try to save the error."); boolean isProcessed = handleException(thread, ex); if (!isProcessed && defaultHandler != null) { //如果用戶沒有處理則讓系統默認的異常處理器來處理 defaultHandler.uncaughtException(thread, ex); } else { //如果自己處理了異常,則不會彈出錯誤對話框,則需要手動退出程序 try { Thread.sleep(3000); } catch (InterruptedException e) { } //干掉自己 android.os.Process.killProcess(android.os.Process.myPid()); //退出程序 System.exit(10); } } /** * 自定義錯誤處理,收集錯誤信息 * 發送錯誤報告等操作均在此完成. * true代表處理該異常,不再向上拋異常, * false代表不處理該異常(可以將該log信息存儲起來)然后交給上層(這里就到了系統的異常處理)去處理, * 簡單來說就是true不會彈出那個錯誤提示框,false就會彈出 */ private boolean handleException(final Thread thread, final Throwable ex) { if (ex == null) { Log.d(logTag, "no exception info."); return false; } //得到詳細的錯誤信息 final String errorInfo = this.getErrorInfo(ex); Log.d(logTag, errorInfo); //得到錯誤信息所保存的文件的絕對路徑 String errorLogFilePath = this.saveToErrorLogFile(errorInfo); if(StringUtils.isNotBlank(errorLogFilePath)){ Log.d(logTag, "error saved in file " + errorLogFilePath); //服務器的接口位置 yxg// String url = URLFactory.getInstance(this.context).getServicesURL().getUploadErrorLogURL(); String url = "http://192.168.18.126:8080/test/upload"; Map<String, Object> upLoadMsgFile=new HashMap<String, Object>(); upLoadMsgFile.put("files",errorLogFilePath); //假如文件路徑不為空,就將錯誤文件上傳到服務器上 HttpClientUpLoadTask uploadFileTask = new HttpClientUpLoadTask(); uploadFileTask.execute(url,JsonUtils.toJson(upLoadMsgFile)); String resultData; try { resultData = uploadFileTask.get(); uploadFileCallBack(resultData, errorLogFilePath); } catch (Exception e) { e.printStackTrace(); } } return false; } //獲取詳細的錯誤信息、應用程序的信息、手機型號版本 private String getErrorInfo(Throwable ex) { List<String> errorContents = new ArrayList<String>(); StackTraceElement[] sts = ex.getStackTrace();//獲取錯誤代碼的位置和信息 if(null != sts){ for(StackTraceElement st : sts){ if(null != st && null != st.toString()){ errorContents.add(st.toString()); } } } @SuppressWarnings("unchecked") Map<String,Object> errorInfoMap = new CaseInsensitiveMap(); //發生錯誤的時間 errorInfoMap.put("errortime", DateFormat.format("yyyy-MM-dd kk:mm:ss", new Date(System.currentTimeMillis()))); //手機型號 errorInfoMap.put("phonetype", android.os.Build.MODEL); errorInfoMap.put("androidsdkversion", android.os.Build.VERSION.SDK); errorInfoMap.put("androidreleaseversion", android.os.Build.VERSION.RELEASE); String localVersion =PackageManagerUtils.getInstance(this.context).getVersionName(); errorInfoMap.put("appversion", localVersion); errorInfoMap.put("errormessage", ex.getMessage()); errorInfoMap.put("errorcontent", errorContents); //上面得到的錯誤信息 (String) return JsonUtils.toJson(errorInfoMap); } //獲取錯誤信息存儲文件的路徑(已經寫入了錯誤信息)返回錯誤文件的位置的絕對路徑 private String saveToErrorLogFile(String errorInfo){ //錯誤文件的名字 String fileName = CrashHandler.this.genErrorFileName(); //錯誤文件的目錄 String fileDir = CrashHandler.this.getLogDir(); try { File errorLogFile = new File(fileDir, fileName); Log.d(CrashHandler.logTag, String.format("save error file is:%s", errorLogFile.getAbsolutePath())); //將錯誤信息寫到文件里面 PrintWriter pw = new PrintWriter(new FileOutputStream(errorLogFile,true)); pw.println(errorInfo); pw.flush(); pw.close(); //getAbsolutePath()得到絕對路徑、全路徑 return errorLogFile.getAbsolutePath(); } catch (Exception e) { Log.e(logTag, "write file error.", e); } return null; } //錯誤文件的目錄 private String getLogDir(){ String logDir = FilePathUtils.getFilePath(this.context); try { File logDirFile = new File(logDir); if (!logDirFile.exists()) { logDirFile.mkdirs(); Log.d(logTag, String.format("make dir success<%s>", logDirFile.getAbsolutePath())); } Log.d(logTag, String.format("log dir is:%s", logDirFile.getAbsolutePath())); } catch (Exception e) { Log.e(logTag, "make dir error.", e); } return logDir; } //將app的名字作為錯誤文件的名字(包含錯誤時間) private String genErrorFileName(){ String fileName = PackageManagerUtils.getInstance(this.context).getAppName(); fileName += "-"; fileName += "error"; fileName += "-"; fileName += FileNameUtils.genFileNameByDateTime();//獲取當前的時間 fileName += ".log"; return fileName; } //根據服務器返回值判定是否上傳成功。(resultCode==0表示上傳成功) private final void uploadFileCallBack(String resultData, String errorLogFilePath ){ if(StringUtils.isBlank(resultData) || StringUtils.isBlank( errorLogFilePath)){ Log.d(logTag, "uploadFileCallBack occur error."); return; } Log.d(logTag, "uploadFileCallBack receive resultData: "+ resultData); Map resultMap = JsonUtils.fromJsonToCaseInsensitiveMap(resultData); int resultCode = MapUtils.getIntValue(resultMap, "resultCode", -1); if(0 == resultCode){ File f = new File( errorLogFilePath); if(f.exists()){ f.delete(); Log.d(logTag, "delete errorlog file ok. "+ errorLogFilePath); }else{ Log.d(logTag, "errorlog file not exists. "+ errorLogFilePath); } }else{ Log.d(logTag, "uploadFileCallBack resultCode=" + resultCode); } }}
新聞熱點
疑難解答