首先,我们定义一个CrashHelper ,继承自UncaughtExceptionHandler ,这个类用来捕获系统出现的异常信息。
/**
* Created by : WGH.
*/
public class CrashHelper implements UncaughtExceptionHandler {
private Context mContext;
private static CrashHelper crashHelper;
private UncaughtExceptionHandler mDefaultHandler;
private CrashHelper() {
}
public static CrashHelper getInstance() {
if (crashHelper == null) {
crashHelper = new CrashHelper();
}
return crashHelper;
}
public void init(Context context) {
mContext = context;
// to get the default UncaughtException of system
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// to set the CrashHandler as the default program handler
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Thread thread, Throwable exception) {
MessageUtil.postAppCrashMsg(exception, mDefaultHandler, thread);
}
}
当系统出现异常的时候,我们就可以在这个uncaughtException()函数中捕获到异常和线程的一些相关信息,这里我们发送了异常的消息,然后就可以在Service中进行处理了。当然,在正常使用之前,还需要进行CrashHelper的初始化,我们将这部分工作放到MyApplication中进行。
代码很简答,如下:
/**
* Created by : WGH.
*/
public class MyApplication extends Application{
private MyApplication mMyApplication;
@Override
public void onCreate() {
super.onCreate();
mMyApplication = this;
CrashHelper handler = CrashHelper.getInstance();
handler.init(getApplicationContext());
}
public static MyApplication context() {
return mMyApplication;
}
public static Gson getGson() {
GsonBuilder builder = new GsonBuilder();
return builder.create();
}
public static DaoMaster getDaoMaster() {
if (daoMaster == null) {
DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(mMyApplication, Define.DBNAME, null);
daoMaster = new DaoMaster(helper.getReadableDatabase());
}
return daoMaster;
}
public static DaoSession getDaoSession() {
if (daoSession == null) {
if (daoMaster == null) {
daoMaster = getDaoMaster();
}
daoSession = daoMaster.newSession();
}
return daoSession;
}
}
可以看到,我们在MyApplication 中做了不少事情:getGson、getDaoSession等,这里初始化异常最主要的代码就是这两句:
CrashHelper handler = CrashHelper.getInstance();
handler.init(getApplicationContext());
在我们捕获到异常的时候,我们会在Service中进行消息的接收,然后对之进行处理(邮件上传)。
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(CrashMessage message) {
switch (message.what) {
case PreDefine.AppCrash:
mThread = message.thread;
mException = message.throwable;
mExceptionHandler = message.exceptionHandler;
handleException(mException);
break;
}
}
可以看到,我们使用了事件总线的方式来接收消息,然后在拿到各个参数后调用handleException(mException)进行后续的逻辑处理。
private boolean handleException(Throwable exception) {
if (exception == null) {
return false;
}
final StackTraceElement[] stack = exception.getStackTrace();
final String message = exception.getMessage();
new Thread() {
@Override
public void run() {
Looper.prepare();
String fileName = Define.LogFileName;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File file = new File(Environment.getExternalStorageDirectory(), fileName);
mFilePath = file.getPath();
try {
FileOutputStream fileOutputStream = new FileOutputStream(file, true);
fileOutputStream.write((message + "\n\n").getBytes());
for (StackTraceElement stackTraceElement : stack) {
fileOutputStream.write(stackTraceElement.toString().getBytes());
}
fileOutputStream.flush();
fileOutputStream.close();
if (NetWorkUtil.isNetWork()) {
String[] toAddress = {PreDefine.getMailNumTo()};
EmailHelper.sendComplex(toAddress, MainActivity.activityMain.getResources()
.getString(R.string.mail_title_crashlog), mEmailSubject, mFilePath);
deleteFile();
}
handleExceptionBySystem();
} catch (Exception e) {
DLog.e(e.toString());
}
}
Looper.loop();
}
}.start();
return true;
}
private void handleExceptionBySystem() {
mExceptionHandler.uncaughtException(mThread, mException);
}
首先,我们通过exception.getStackTrace()获取到异常信息栈,然后通过exception.getMessage()获取异常信息,最后开启子线程将异常信息写入到文件流并发送出去。
关于邮件的逻辑我就不详细介绍了,感兴趣的可以参阅我的项目源码:。。。
联系方式:
简书:WillFlow
CSDN:WillFlow
微信公众号:WillFlow