針對(duì)Crash,Android默認(rèn)的處理方式是甥绿,退出App绞幌、彈一個(gè)提示框蕾哟。
這樣的反饋難免有些暴力,還丑莲蜘,我們需要更溫和一點(diǎn)的提示谭确,于是自定義UncatchExceptionHandler來截獲處理Crash:
/**
* 初始化
*
* @param context
*/
public void init(Context context) {
mContext = context;
// 獲取系統(tǒng)默認(rèn)的UncaughtException處理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// 設(shè)置該CrashHandler為程序的默認(rèn)處理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
/**
* 當(dāng)UncaughtException發(fā)生時(shí)會(huì)轉(zhuǎn)入該函數(shù)來處理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
//如果用戶沒有處理則讓系統(tǒng)默認(rèn)的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
// 暫停3秒
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
/**
* 自定義錯(cuò)誤處理,收集錯(cuò)誤信息 發(fā)送錯(cuò)誤報(bào)告等操作均在此完成.
*
* @param ex
* @return true:如果處理了該異常信息;否則返回false.
*/
private boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
// 使用Toast來顯示異常信息
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "程序出現(xiàn)異常,即將退出~", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
return true;
}
效果如下:
但是問題也隨之而來票渠,自定義CrashHandler在退出App之后逐哈,<b>會(huì)重啟當(dāng)前奔潰的Activity</b>,如果奔潰的是LaunchActivity问顷,那么會(huì)不斷奔潰昂秃、重啟、奔潰杜窄、重啟……當(dāng)然肠骆,也不用擔(dān)心進(jìn)入死循環(huán)(系統(tǒng)有做限制),但是體驗(yàn)極差羞芍。
于是對(duì)比Logcat日志:
<pre>
系統(tǒng)默認(rèn)Handler
I/ActivityManager( 1238): Process com.netease.mail.oneduobaohydrid.debug (pid 2780) has died
W/ActivityManager( 1238): Scheduling restart of crashed service com.netease.mail.oneduobaohydrid.debug/com.netease.mail.oneduobaohydrid.service.CommonService in 1000ms
……
I/ActivityManager( 1238): Start proc com.netease.mail.oneduobaohydrid.debug for service com.netease.mail.oneduobaohydrid.debug/com.netease.mail.oneduobaohydrid.service.CommonService: pid=2819 uid=10054 gids={50054, 9997, 1028, 1015, 3003} abi=x86
</pre>
<pre>
自定義Handler
I/ActivityManager( 1238): Process com.netease.mail.oneduobaohydrid.debug (pid 2993) has died
W/ActivityManager( 1238): Scheduling restart of crashed service com.netease.mail.oneduobaohydrid.debug/com.netease.mail.oneduobaohydrid.service.CommonService in 64000ms
……
I/ActivityManager( 1238): Start proc com.netease.mail.oneduobaohydrid.debug for activity com.netease.mail.oneduobaohydrid.debug/com.netease.mail.oneduobaohydrid.activity.MainActivity: pid=3030 uid=10054 gids={50054, 9997, 1028, 1015, 3003} abi=x86
</pre>
相同點(diǎn):Crash之后App對(duì)應(yīng)的Process都被殺死哗戈,然后都安排重啟Service。
不同點(diǎn):自定義CrashHandler荷科,存在一個(gè)由ActivityManager啟動(dòng)對(duì)應(yīng)Activity的系統(tǒng)行為唯咬。
多放查閱資料纱注,發(fā)現(xiàn)App Crash之后系統(tǒng)會(huì)重新啟動(dòng)Task棧頂?shù)腁ctivity,具體請(qǐng)自行g(shù)oogle胆胰!
<b>解決方法是:</b>在殺死App對(duì)應(yīng)Process之前狞贱,結(jié)束掉Task棧中所有的Activity。
/**
* 當(dāng)UncaughtException發(fā)生時(shí)會(huì)轉(zhuǎn)入該函數(shù)來處理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
//如果用戶沒有處理則讓系統(tǒng)默認(rèn)的異常處理器來處理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
// 暫停3秒
Thread.sleep(3000);
} catch (InterruptedException e) {
Log.e(TAG, "error : ", e);
}
// 結(jié)束所有Activity
OneApplication.finishAllActivities();
// 退出程序
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
}
}
核心代碼:OneApplication.finishAllActivities();
http://stackoverflow.com/questions/5423571/prevent-activity-stack-from-being-restored
https://groups.google.com/forum/#!topic/android-developers/snTPpksX9TU