在某些手機或者平板上,android程序崩潰後,系統會根據堆棧信息強行把應用重新拉起。但是這種強行重啓應用,會一些數據缺失的問題,造成二次崩潰,這樣的體驗是十分不好的。
所以我的目標就是崩潰後不要重新拉起應用。
如何解決崩潰後重新的問題,可以參見下面的文章,本文不做過多的描述,清空activityStack即可。
Android 解決應用崩潰後重啓的問題
核心代碼如下:
public class BuglyCrashHandler implements Thread.UncaughtExceptionHandler {
List<Activity> activities = new ArrayList<>();
static BuglyCrashHandler instance;
public BuglyCrashHandler(Application application) {
exceptionHandler = handler;
registerActivityListener(application);
}
@Override
public void uncaughtException(Thread t, Throwable e) {
clearAllActivity();
}
public void clearAllActivity() {
for (Activity activity : activities) {
if (null != activity) {
activity.finish();
}
}
}
private void registerActivityListener(Application application) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
/**
* 監聽到 Activity創建事件 將該 Activity 加入list
*/
activities.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (null == activities && activities.isEmpty()) {
return;
}
if (activities.contains(activity)) {
/**
* 監聽到 Activity銷燬事件 將該Activity 從list中移除
*/
activities.remove(activity);
}
}
});
}
}
}
application調用如下方法:
Thread.setDefaultUncaughtExceptionHandler(new BuglyCrashHandler(application);
一般這樣做是沒有問題的,但是如果引入了bugly,那就有問題了。bugly也使用的是Thread.setDefaultUncaughtExceptionHandler(this)方式,則只會有一個生效。BuglyCrashHandler會和bugly默認的UncaughtExceptionHandler衝突,這就是本文要解決的重點。
所以我們可以簡單的改一下,使用自定義的UncaughtExceptionHandler,然後在uncaughtException中昨晚自己的事情後,再把異常轉交給bugly的UncaughtExceptionHandler。如下:
public class BuglyCrashHandler implements Thread.UncaughtExceptionHandler {
Thread.UncaughtExceptionHandler exceptionHandler;
List<Activity> activities = new ArrayList<>();
static BuglyCrashHandler instance;
public BuglyCrashHandler(Application application, Thread.UncaughtExceptionHandler handler) {
exceptionHandler = handler;
registerActivityListener(application);
instance = this;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
if (exceptionHandler != null) {
exceptionHandler.uncaughtException(t, e);
}
clearAllActivity();
android.os.Process.killProcess(android.os.Process.myPid());
}
public void clearAllActivity() {
for (Activity activity : activities) {
if (null != activity) {
activity.finish();
}
}
}
public static BuglyCrashHandler getInstance() {
return instance;
}
private void registerActivityListener(Application application) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
/**
* 監聽到 Activity創建事件 將該 Activity 加入list
*/
activities.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (null == activities && activities.isEmpty()) {
return;
}
if (activities.contains(activity)) {
/**
* 監聽到 Activity銷燬事件 將該Activity 從list中移除
*/
activities.remove(activity);
}
}
});
}
}
}
application中使用方式如下:
注意調用順序,必須在bugly調用之後在調用。
Thread.setDefaultUncaughtExceptionHandler(new BuglyCrashHandler(application, Thread.getDefaultUncaughtExceptionHandler()));
但是實際驗證下來,程序還是會被重新啓動。於是乎,繼續debug驗證,發現bugly的異常處理又阻斷效果。
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.i("lxl", "uncaughtException before:thread:" + Thread.currentThread().getName());
if (exceptionHandler != null) {
exceptionHandler.uncaughtException(t, e);
}
//後面的代碼都不會被執行
clearAllActivity();
android.os.Process.killProcess(android.os.Process.myPid());
Log.i("lxl", "uncaughtException after");
}
於是懷疑是bugly的異常處理中,應該調用了殺死進程一類的操作,所以導致後面的代碼沒有執行。於是稍微改了下,最終代碼如下,完美解決了程序崩潰後重啓與bugly的衝突。
public class BuglyCrashHandler implements Thread.UncaughtExceptionHandler {
Thread.UncaughtExceptionHandler exceptionHandler;
List<Activity> activities = new ArrayList<>();
static BuglyCrashHandler instance;
public BuglyCrashHandler(Application application, Thread.UncaughtExceptionHandler handler) {
exceptionHandler = handler;
registerActivityListener(application);
instance = this;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
clearAllActivity();
if (exceptionHandler != null) {
exceptionHandler.uncaughtException(t, e);
}
}
public void clearAllActivity() {
for (Activity activity : activities) {
if (null != activity) {
activity.finish();
}
}
}
public static BuglyCrashHandler getInstance() {
return instance;
}
private void registerActivityListener(Application application) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
/**
* 監聽到 Activity創建事件 將該 Activity 加入list
*/
activities.add(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (null == activities && activities.isEmpty()) {
return;
}
if (activities.contains(activity)) {
/**
* 監聽到 Activity銷燬事件 將該Activity 從list中移除
*/
activities.remove(activity);
}
}
});
}
}
}