public class CrashHandler implements UncaughtExceptionHandler {
private static final String TAG = "NorrisInfo";
private UncaughtExceptionHandler mDefaultHandler;
private static CrashHandler mInstance = new CrashHandler();
private Context mContext;
private Map<String, String> mLogInfo = new HashMap();
private SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyyMMdd_HH-mm-ss");
private Thread paramThread;
private Throwable paramThrowable;
private CrashHandler.CrashHandlerCallback crashHandlerCallback;
private CrashHandler() {
}
public static CrashHandler getInstance() {
return mInstance;
}
public void init(Context paramContext, CrashHandler.CrashHandlerCallback crashHandlerCallback) {
this.crashHandlerCallback = crashHandlerCallback;
this.mContext = paramContext;
this.mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
this.paramThread = paramThread;
this.paramThrowable = paramThrowable;
this.handleException();
}
public boolean handleException() {
if(this.paramThrowable == null) {
return false;
} else {
(new Thread() {
public void run() {
Looper.prepare();
Toast.makeText(CrashHandler.this.mContext, "很抱歉,程序出现异常,即将退出", 0).show();
Looper.loop();
}
}).start();
this.getDeviceInfo(this.mContext);
this.saveCrashLogToFile();
return true;
}
}
public void getDeviceInfo(Context paramContext) {
try {
PackageManager mFields = paramContext.getPackageManager();
PackageInfo field = mFields.getPackageInfo(paramContext.getPackageName(), 1);
if(field != null) {
String versionName = field.versionName == null?"null":field.versionName;
String versionCode = String.valueOf(field.versionCode);
this.mLogInfo.put("versionName", versionName);
this.mLogInfo.put("versionCode", versionCode);
}
} catch (NameNotFoundException var10) {
var10.printStackTrace();
}
Field[] var11 = Build.class.getDeclaredFields();
Field[] var6 = var11;
int var14 = var11.length;
for(int var13 = 0; var13 < var14; ++var13) {
Field var12 = var6[var13];
try {
var12.setAccessible(true);
this.mLogInfo.put(var12.getName(), var12.get("").toString());
Log.d("NorrisInfo", var12.getName() + ":" + var12.get(""));
} catch (IllegalArgumentException var8) {
var8.printStackTrace();
} catch (IllegalAccessException var9) {
var9.printStackTrace();
}
}
}
private String saveCrashLogToFile() {
UsualTools.showPrintMsg("saveCrashLogToFile");
StringBuffer mStringBuffer = new StringBuffer();
Iterator mPrintWriter = this.mLogInfo.entrySet().iterator();
String mResult;
while(mPrintWriter.hasNext()) {
Entry mWriter = (Entry)mPrintWriter.next();
String mThrowable = (String)mWriter.getKey();
mResult = (String)mWriter.getValue();
mStringBuffer.append(mThrowable + "=" + mResult + "\r\n");
}
StringWriter mWriter1 = new StringWriter();
PrintWriter mPrintWriter1 = new PrintWriter(mWriter1);
this.paramThrowable.printStackTrace(mPrintWriter1);
this.paramThrowable.printStackTrace();
for(Throwable mThrowable1 = this.paramThrowable.getCause(); mThrowable1 != null; mThrowable1 = mThrowable1.getCause()) {
mThrowable1.printStackTrace(mPrintWriter1);
mPrintWriter1.append("\r\n");
}
mPrintWriter1.close();
mResult = mWriter1.toString();
mStringBuffer.append(mResult);
String mTime = this.mSimpleDateFormat.format(new Date());
String mFileName = "CrashLog-" + mTime + ".log";
if(Environment.getExternalStorageState().equals("mounted")) {
try {
File e = new File(Environment.getExternalStorageDirectory() + "/CrashInfos");
Log.v("NorrisInfo", e.toString());
if(!e.exists()) {
e.mkdir();
}
FileOutputStream mFileOutputStream = new FileOutputStream(e + "/" + mFileName);
mFileOutputStream.write(mStringBuffer.toString().getBytes());
mFileOutputStream.close();
this.crashHandlerCallback.onCrashHandle(e, e + "/" + mFileName, mStringBuffer.toString());
return mFileName;
} catch (FileNotFoundException var10) {
var10.printStackTrace();
} catch (IOException var11) {
var11.printStackTrace();
}
}
return null;
}
public void letDefaultHandlerDeal() {
this.mDefaultHandler.uncaughtException(this.paramThread, this.paramThrowable);
}
public interface CrashHandlerCallback {
void onCrashHandle(File var1, String var2, String var3);
}
}
捕获异常以后直接在Application或者Activity的onCreate方法中加入以下两句调用即可
CrashHandler crashHandler = CrashHandler.getInstance();
crashHandler.init(getApplicationContext());
现在安装 Android 系统的手机版本和设备千差万别,在模拟器上运行良好的程序安装到某款手机上说不定就出现崩溃的现象,开发者个人不可能购买所有设备逐个调试,所以在程序发布出去之后,如果出现了崩溃现象,开发者应该及时获取在该设备上导致崩溃的信息,这对于下一个版本的bug修复帮助极大,所以今天就来介绍一下如何在程序崩溃的情况下收集相关的设备参数信息和具体的异常信息,并发送这些信息到服务器供开发者分析和调试程序。
android.app.Application 和j ava.lang.Thread.UncaughtExceptionHandler。
Application:用来管理应用程序的全局状态。在应用程序启动时Application会首先创建,然后才会根据情况(Intent)来启动相应的Activity和Service。
Thread.UncaughtExceptionHandler:线程未捕获异常处理器,用来处理未捕获异常。如果程序出现了未捕获异常,默认会弹出系统中强制关闭对话框。我们需要实现此接口,并注册为程序中默认未捕获异常处理。这样当未捕获异常发生时,就可以做一些个性化的异常处理操作。