點此進入目錄:[干貨] 十天 教你從創(chuàng)意到上線APP
一厂画、異常的捕獲
1凸丸、異常捕獲類
首先,我們定義一個CrashHelper 袱院,繼承自UncaughtExceptionHandler 屎慢,這個類用來捕獲系統(tǒng)出現(xiàn)的異常信息。
/**
* 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);
}
}
當(dāng)系統(tǒng)出現(xiàn)異常的時候忽洛,我們就可以在這個uncaughtException()函數(shù)中捕獲到異常和線程的一些相關(guān)信息腻惠,這里我們發(fā)送了異常的消息,然后就可以在Service中進行處理了欲虚。當(dāng)然集灌,在正常使用之前,還需要進行CrashHelper的初始化复哆,我們將這部分工作放到MyApplication中進行欣喧。
2腌零、全局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());
二驯鳖、異常的傳遞和處理
1闲询、接收異常消息
在我們捕獲到異常的時候,我們會在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;
}
}
可以看到,我們使用了事件總線的方式來接收消息摔握,然后在拿到各個參數(shù)后調(diào)用handleException(mException)進行后續(xù)的邏輯處理寄狼。
2、處理異常消息
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()獲取異常信息,最后開啟子線程將異常信息寫入到文件流并發(fā)送出去盛正。
關(guān)于郵件的邏輯我就不詳細(xì)介紹了删咱,感興趣的可以參閱我的項目源碼:GitHub
聯(lián)系方式: