Android捕获全局异常并以文件或者异常内容发送给指定服务器

来源:互联网 发布:摄影师作品网站知乎 编辑:程序博客网 时间:2024/06/06 05:27

app应用的全局异常捕获,是每个上线应用或者测试应用必备的一个功能,同时若是能够将捕获到的异常信息上送到指定的服务器地址,那将便于我们去分析app的缺陷之处,便于我们去完善app的相关功能。

package com.zqh.crash.crashhandler.utils;import android.content.Context;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.PackageManager.NameNotFoundException;import android.os.Build;import android.text.TextUtils;import android.util.Log;import com.zqh.crash.crashhandler.app.MyApplication;import java.io.File;import java.io.PrintWriter;import java.io.StringWriter;import java.io.Writer;import java.lang.Thread.UncaughtExceptionHandler;import java.lang.reflect.Field;import java.util.Date;import java.util.HashMap;import java.util.Locale;import java.util.Map;/** * 全局异常处理类 * */public abstract class CrashHandler implements UncaughtExceptionHandler {/** 系统默认的UncaughtException处理类 **/private UncaughtExceptionHandler mDefaultHandler;/** 程序context **/protected MyApplication mContext;/** 存储设备信息和异常信息 **/private Map<String, String> mInfos = new HashMap<String, String>();/** 设置crash文件位置 **/private String mDRCrashFilePath;/** 生成的crash文件 **/private File crashFile;/** * 初始化 *  * @param context */public void init(MyApplication context) {// 1、上下文mContext = context;// 2、获取系统默认的UncaughtException处理器mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 3、初始化参数initParams();// 4、设置当前CrashHandler为默认处理异常类Thread.setDefaultUncaughtExceptionHandler(this);}/** * 3.1 初始化参数 <br/> * 如果想使用自己的CrashHandler,则复写initParams()方,然后设置参数<br/> */public abstract void initParams();@Overridepublic void uncaughtException(Thread thread, Throwable ex) {if (mDefaultHandler != null && !handlerException(ex)) {mDefaultHandler.uncaughtException(thread, ex);} else {// 程序休眠3s后退出try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.exit(0);}}/** * 5、处理异常<br> * <br> *  * 5.1 收集设备参数信息<br> * 5.2 弹出窗口提示信息<br> * 5.3 保存log和crash到文件<br> * 5.4 发送log和crash到服务器<br> *  * @param ex * @return 是否处理了异常 */protected boolean handlerException(Throwable ex) {if (ex == null) {return false;} else {// 5.1 收集设备参数信息collectDeviceInfo(mContext);// 5.3 保存log和crash到文件saveLogAndCrash(ex);// 5.4 发送log和crash到服务器sendLogAndCrash();return true;}}/** * 5.1 收集设备信息 *  * @param ctx */protected void collectDeviceInfo(Context ctx) {try {PackageManager pm = ctx.getPackageManager();PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),PackageManager.GET_ACTIVITIES);if (pi != null) {String versionName = pi.versionName == null ? "null": pi.versionName;String versionCode = pi.versionCode + "";String packName = pi.packageName;mInfos.put("versionName", versionName);mInfos.put("versionCode", versionCode);mInfos.put("packageName", packName);mInfos.put("sdkVersion", Build.VERSION.RELEASE);}} catch (NameNotFoundException e) {Log.e("zqh", "An error occured when collect package info, Error: "+ e);}Field[] fields = Build.class.getDeclaredFields();for (Field field : fields) {try {field.setAccessible(true);mInfos.put(field.getName(), field.get(null).toString());} catch (Exception e) {Log.e("zqh","An error occured when collect crash info, Error: " + e);}}}/** * 5.3 保存log和crash到文件 *  * @param ex */protected void saveLogAndCrash(Throwable ex) {StringBuffer sb = new StringBuffer();sb.append("[DateTime: " + DateUtil.date2String(new Date()) + "]\n");sb.append("[DeviceInfo: ]\n");// 遍历infosfor (Map.Entry<String, String> entry : mInfos.entrySet()) {String key = entry.getKey().toLowerCase(Locale.getDefault());String value = entry.getValue();if (!TextUtils.isEmpty(key)) {if (key.equals("fingerprint") || key.equals("versionname")|| key.equals("versioncode")|| key.equals("packagename")|| key.equals("display")|| key.equals("serial")|| key.equals("sdkversion")) {sb.append("" + key + ": " + value + "\n");}}}// 将错误手机到writer中Writer writer = new StringWriter();PrintWriter pw = new PrintWriter(writer);ex.printStackTrace(pw);Throwable cause = ex.getCause();while (cause != null) {cause.printStackTrace(pw);cause = cause.getCause();}pw.close();String result = writer.toString();sb.append("[Excetpion: ]\n");sb.append(result);// 5.3.1 记录异常到特定文件中saveToCrashFile(sb.toString());}/** * 5.3.1写入文本 *  * @param crashText */protected void saveToCrashFile(String crashText) {Log.d("zqh", "CrashHandler is writing crash-info to CrashFile("+ this.mDRCrashFilePath + ")! ");crashFile = new File(mDRCrashFilePath);// 创建文件FileUtil.createFileAndFolder(crashFile);// 追加文本FileUtil.appendToFile(crashFile, crashText);}/** * 5.4 发送log和crash到服务器 */protected void sendLogAndCrash() {crashFile = new File(getDRCrashFilePath());// 5.4.1sendToServer(crashFile);}/** * 5.4.1 将错误报告发送到服务器 *  * @param crashFile */protected abstract void sendToServer(File crashFile);public String getDRCrashFilePath() {return mDRCrashFilePath;}/** * 设置记录崩溃信息的文件位置 *  * @param mDRCrashFilePath */public void setDRCrashFilePath(String mDRCrashFilePath) {this.mDRCrashFilePath = mDRCrashFilePath;}}

package com.zqh.crash.crashhandler.app;import android.app.Application;import android.os.Build;import android.util.Log;public class MyApplication extends Application {private static MyApplication instance;@Overridepublic void onCreate() {super.onCreate();this.instance = this;Log.e("zqh","DRApplication: initCrashHandler()");MyCrashHandler.getInstance().init(this);}/** * 手机的版本 比如5.1.1 */public String getOsVersion() {return Build.VERSION.RELEASE;}/** * 手机名称 比如"devicemodel": "AOSP on HammerHead", *  * @return */public String getDevice() {return Build.MODEL;}public static MyApplication getInstance() {return instance;}}

github源码地址:github源码地址

原创粉丝点击