当程序崩溃(Crash)的时候,默认是不对异常信息做处理的。如果想要把异常信息保存到本地文件中,或上传的服务器。那么就要借助UncaughtExceptionHandler这个类。
首先,实例化UncaughtExceptionHandler,代码如下:
public class ForceCloseHandler implements Thread.UncaughtExceptionHandler {
public static final String LOG_FILE_NAME = "forceclose.log";
private static ForceCloseHandler inst ;
public static ForceCloseHandler getInstance() {
if(inst==null)inst = new ForceCloseHandler();
return inst;
}
private Context mContext;
private Thread.UncaughtExceptionHandler mExceptionHandler;
private JSONObject jsonObject;
private ForceCloseHandler() {}
public void init(Context context) {
mContext = context;
mExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
private void handleUncaughtException(Throwable ex) {
if (ex == null) return;
try {
if(jsonObject ==null)jsonObject = new JSONObject();
saveDeviceInfo();
saveForceCloseInfo2File(ex);
// 把异常信息发送到服务器
ForceCloseFeedBack.getInstance().feedBack(mContext, jsonObject.toString());
} catch (Exception e) {
LogUtil.w(e);
}
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
handleUncaughtException(throwable);
if (throwable != null) LogUtil.w(throwable);
mExceptionHandler.uncaughtException(thread, throwable);
}
public void saveDeviceInfo() throws JSONException {
TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
jsonObject.put("platform", "android");
jsonObject.put("model", Build.MODEL);
jsonObject.put("trackid", AppConfig.PARTNER_ID);
jsonObject.put("product", AppConfig.CLIENT_TAG);
jsonObject.put("os_version", Build.VERSION.RELEASE);
jsonObject.put("deviceid", DeviceInfo.getDeviceId());
jsonObject.put("net_type", tm.getNetworkOperator());
jsonObject.put("timestamp", System.currentTimeMillis());
jsonObject.put("app_version", Application.getInstance().getVersionCode());
}
private void saveForceCloseInfo2File(Throwable ex) throws Exception {
StringWriter 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() + "\n";
jsonObject.put("errorDetail", result);
if (AppConfig.LOG_ERR_SAVE) {
File file = FileHelper.getDiskCacheDir(mContext, LOG_FILE_NAME);
FileOutputStream fos = new FileOutputStream(file, true);
fos.write(jsonObject.toString().getBytes());
fos.close();
}
}
}
接下来,看看这个实例化后的类怎么使用,代码如下:
public class Application extends android.app.Application {
private static Application instance;
public Context currentContext;
public static Application getInstance() {
return instance;
}
@Override
public void onCreate() {
super.onCreate();
init();
}
public void init() {
instance = this;
if (Config.LOG_ERR_FEED) {
ForceCloseHandler.getInstance().init(instance);
}
}
@Override
public void onTerminate() {
super.onTerminate();
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
}
非常简单,只要在指定的Application类的onCreate()回调中,把UncaughtExceptionHandler和Application的实例绑定在一起就可以了。关键代码如下:
public void init(Context context) {
mContext = context;
mExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
}
这样,如果程序崩溃,错误日志就会被保存在本地,同时又被上传到了服务器。