Android-Crash处理----崩溃后禁止默认重启与崩溃后手动重启
来源:互联网 发布:python cst时间转换 编辑:程序博客网 时间:2024/06/11 23:46
转载请注明出处。
伸手党福利:compile ‘com.tuzhenlei:crashhandler:1.0.1’ ,详情参见文档和demo:github地址
Crash相信是很多朋友开发过程经常遇到的问题。经过本人测试,Android在API21以下(也就是Android5.0以下),crash后会直接退出应用;但是在API21以上(5.0以上系统),会遵循以下原则重启:
1. 包含service, 如果程序crash的时候,运行着service,那么系统会重新启动service 。
2. 不包含service,只有一个Activity,那么系统不会重新启动该Activity 。
3. 不包含service,但是当前栈中包含两个Activity, A–>B, 如果B crash,那么系统会重启A。
4. 不包含service,但是当前栈中包含三个Activity, A–>B–>C, 如果C crash,那么系统会重启B,并且A仍然存在,即可以从重启的Back到A。
我们来看下没有进过任何处理的3种crash情况,3张图分别对应第2,第3,第4种情况
所以我们根据项目需求以及实际情况有两种解决方案,都可以避免无限crash或者是丢失必要的传递信息引起其他的crash,从而造成非常差的用户体验的情况。
1. crash后不重启APP,让用户手动重启。
2. crash后1秒重启APP。
首先,我们写一个crashHandler类,继承UncaughtExceptionHandler
CrashHandler implements Thread.UncaughtExceptionHandler
然后初始化crashhandler的时候设置CrashHandler为程序的默认处理器,同时获取系统默认的UncaughtException处理器
Thread.setDefaultUncaughtExceptionHandler(this);mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
在需要复写的uncaughtException方法中进行我们需要的处理,这里关键就是在必须要先关闭栈内所有的activity,再退出APP:
/** * 当UncaughtException发生时会转入该函数来处理 */@Overridepublic void uncaughtException(Thread thread, Throwable ex) { boolean isHandle = handleException(ex); if (!isHandle && mDefaultHandler != null) { // 如果我们没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { try { //给Toast留出时间 Thread.sleep(2800); } catch (InterruptedException e) { Log.e(TAG, "uncaughtException() InterruptedException:" + e); } if (mIsRestartApp) { //利用系统时钟进行重启任务 AlarmManager mgr = (AlarmManager) mApplication.getSystemService(Context.ALARM_SERVICE); try { Intent intent = new Intent(mApplication, mClassOfFirstActivity); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent restartIntent = PendingIntent.getActivity(mApplication, 0, intent, PendingIntent.FLAG_ONE_SHOT); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + mRestartTime, restartIntent); // x秒钟后重启应用 } catch (Exception e) { Log.e(TAG, "first class error:" + e); } } mMyActivityLifecycleCallbacks.removeAllActivities(); android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); System.gc(); }}
handleException的方法主要是为了弹出Toast和收集crash信息
/** * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成. * * @param ex * @return true:如果处理了该异常信息;否则返回false. */private boolean handleException(Throwable ex) { if (!hasToast) { new Thread(new Runnable() { @Override public void run() { try { Looper.prepare(); Toast toast; if (mCustomToast == null) { toast = Toast.makeText(mApplication, mCrashTip, Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); } else { toast = mCustomToast; } toast.show(); Looper.loop(); hasToast = true; } catch (Exception e) { Log.e(TAG, "handleException Toast error" + e); } } }).start(); } if (ex == null) { return false; } if (mIsDebug) { // 收集设备参数信息 collectDeviceInfo(); // 保存日志文件 saveCatchInfo2File(ex); } return true;}
由于我们要关闭栈内所有activity,所以要监听每个activity的生命周期,建议直接在application里面注册一个ActivityLifecycleCallbacks,实现如下:
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)public class MyActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {private List<Activity> activities = new LinkedList<>();public static int sAnimationId = 0;@Overridepublic void onActivityCreated(Activity activity, Bundle savedInstanceState) { addActivity(activity);}@Overridepublic void onActivityStarted(Activity activity) {}@Overridepublic void onActivityResumed(Activity activity) {}@Overridepublic void onActivityPaused(Activity activity) {}@Overridepublic void onActivityStopped(Activity activity) {}@Overridepublic void onActivitySaveInstanceState(Activity activity, Bundle outState) {}@Overridepublic void onActivityDestroyed(Activity activity) { removeActivity(activity);}/** * 添加Activity */public void addActivity(Activity activity) { if (activities == null) { activities = new LinkedList<>(); } if (!activities.contains(activity)) { activities.add(activity);//把当前Activity添加到集合中 }}/** * 移除Activity */public void removeActivity(Activity activity) { if (activities.contains(activity)) { activities.remove(activity); } if (activities.size() == 0) { activities = null; }}/** * 销毁所有activity */public void removeAllActivities() { for (Activity activity : activities) { if (null != activity) { activity.finish(); activity.overridePendingTransition(0, sAnimationId); } }}}
然后用appliction.registerActivityLifecycleCallbacks(new MyActivityLifecycleCallbacks());即可。
经过我们处理后的情况如下图所示:
这样问题就解决了(已封装好,直接依赖即可使用)。
- Android-Crash处理----崩溃后禁止默认重启与崩溃后手动重启
- Android异常崩溃Crash重启方案
- Android异常崩溃Crash重启方案
- Android异常崩溃Crash重启方案
- Android 如何自定义CrashHandler与崩溃后自动重启
- android app崩溃后自动重启
- android崩溃重启
- android崩溃重启
- android处理crash程序崩溃异常
- android处理crash程序崩溃异常
- 安卓APP崩溃(crash)后重新启动,捕获全局异常重启APP
- Android程序崩溃重启
- Android程序崩溃重启
- 【Android】App应用崩溃(Crash/Force Close)之后如何让它自动重启?
- APP崩溃后自动重启
- 【crash策略】Android中处理崩溃异常策略
- (4.1.35.1) android处理crash程序崩溃异常
- Android 程序崩溃后的处理
- qt5.9 子项目创建及qt项目管理
- Android 7.1 源码下载编译 (Ubuntu 14.0.4 环境下)
- 如何在右击菜单中添加新建项
- navicat报错ora28547
- 解决poi操作docx替换${}占位符不成功的过程
- Android-Crash处理----崩溃后禁止默认重启与崩溃后手动重启
- 欢乐斗地主玩法规则
- 没网?没问题。用Air Gap使用Artifactory
- 菜鸟的第一篇博客
- 程序集、命名空间和类
- c# 嵌套类
- 大数据揭秘:低学历成功逆袭概率多少?结果令人震惊!
- H5游戏将要带来新变局
- 8.2(3)