“安全模式”:App的启动保护实践。
App 启动期间连续崩溃时,客户端的分级执行策略。
背景&痛点&价值
对于一个商业项目而言,质量是研发同学的生命线。
试想一下,如果项目上线出现大面积的用户崩溃以及不可用,那简直是研发同学的噩梦。
这里有同学就要提问了:诸多大型商业项目在性能检测、优化与高可用上花费大力气,也产出了各种APM(application performance management应用性能管理)工具及HotFix(热修复)方案,没有用吗?
再试想下,如果应用在启动时期,因为第三方SDK初始化出错而导致连续崩溃,而HotFix无法生效。连续的启动崩溃体验极其糟糕,你说用户最终会卸载吗?
启动崩溃的诱因有:
- 各种三方 SDK 初始化配置出错;
- 各种文件包括但不限于数据库、XML 的拷贝或操作失败;
- 各种网络请求下发了脏数据;
- 各种资源包的下载、合并导致的脏数据,包括但不限于闪屏图、Zip 包、修复包等;
- 用户由跨 N 多个版本的低版本 App 升级到最新版引发的脏数据。
大家不要觉得我在危言耸听,我举一个我们iOS实际的例子:有次某广告商大大服务端下发错误字段,导致应用读取解析失败,App启动奔溃,用户再也进不了应用。对我们的伤害是巨大的,对我们的教训是惨痛的。
随之而来的问题就是,谁来解决启动阶段的崩溃,怎么解决呢?
历经N个月的摸索,跨越众多版本,以及小渠道的实践,应用启动阶段的安全模式就应运而生了。
安全模式的设计
七猫安全模式致力于解决APP启动阶段的崩溃等问题,同时具备配置中心、自主修复、动态修复、数据中心、测试五个方面,是一整套启动保护的解决方案。
- 配置中心: SDK配置开关、新老功能可切换
- 自主修复:在APP连续Crash情况下具备分级、无感自修复能力:安全模式的一级修复策略,二级修复策略
- 动态修复:热修复能力、可监控、灰度、回滚、清除
- 数据中心:监控告警功能,让你及时发现问题;重点问题日志排查分析
- 快速测试:针对测试加入特殊处理(开发模拟连续崩溃工具,见下图),提高测试效率。优化预发环境下测试,优化每次回归验证安全模式的难度
策略方案
安全模式的策略方案分为三点,具体描述见以下条目:
1、捕获异常
1.1 异常分类:
检测连续闪退,可以通过捕获异常来实现,异常分几种:
- RuntimeException --设置主线程的 UncaughtExceptionHandler 来捕获运行时的崩溃
- ANR --无法捕获的
- Native 信号异常–注册信号处理函数,捕捉 native crash
1.2 崩溃的捕获:
设置主线程的 UncaughtExceptionHandler 来捕获运行时的崩溃
在 Application 中执行相应保护策略:
private int crashNum;//崩溃次数
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
if(crashNum> 3){
// 删除文件,恢复到重新安装的状态
}
if(crashNum> 5){
// 清除热修信息
}
}
1.3 优缺点
- 可能会与项目中已有的第三方异常收集框架冲突,漏检测。
- 可能会与项目中已有的异常处理耦合,代码逻辑混乱。
- 最大问题是不够准确,缺少对 Native 的异常处理。
2、标记数
2.1 前言
天猫安全模式原理:APP crash 的原因有很多,每个 APP 设计的方案也有不同,将其所有的异常错误都捕捉到很困难,因此我们换了个方式,完全从用户的角度来思考什么是异常退出,也就是打标记 flag 方式。
2.2 思路
- 进入应用的时候就记录一个崩溃次数,在满足一定条件之后则认为启动阶段没有异常,同时将崩溃次数重置回复初始状态。
- 异常次数到达一定程度则进入安全模式。
- 需要维护一个崩溃次数,进入应用就把崩溃次数 +1
2.3崩溃次数重置时机
满足一定条件则重置崩溃次数:
- 完成二级修复策略
- 用户正常启动应用满 10 秒
- 用户正常退出应用
- 用户主动从前台切换到后台
2.4分级修复策略
- 一级修复策略:业务线行为;更新 SDK 网络配置;
- 二级修复策略:清空整个 App 数据,重置至初始安装状态;清除热修复包或者别的资源包;
- 阻塞修复策略:阻塞进程,优先执行预设任务,例如:请求以及运行热修复包,等待全部完成之后再执行正常流程;
- 多次请求失败后禁止请求(给服务端减压)
2.5 优缺点:
- 标记数逻辑简单,与已有代码耦合小。
- 在启动阶段,用户从前台切换到后台时,用户是否强杀了 APP 又或者多久又切回来都不清楚,对 crashCount 值是否准确有影响。
3、页面生命周期内的异常捕获
3.1前言
很多时候由于一些微不足道的 bug 导致 app 崩溃很可惜,Android 默认的异常杀进程机制简单粗暴,但很多时候让 app 崩溃其实也并不能解决问题。
有些 bug 可能是系统 bug,对于这些难以预料的系统 bug 我们不好绕过。还有一些 bug 是我们自己编码造成的,对于有些 bug 来说直接忽略掉的话可能只是导致部分不重要的功能没法使用而已,又或者对用户来说完全没有影响,这种情况总比每次都崩溃要好很多。
3.2 简介
activity lifecycle exception catch:在执行 Activity 或 Service 生命周期发生异常时对该异常的捕获和处理方式,用来降低一些非必要的 crash。
3.3 小渠道探索与实践
在注册全局异常捕获时,控制在页面Activity生命周期内是否捕获Hook。
测试发现确实可以捕获在页面生命周期中的ActivityThread引发的异常,比如,我们模拟个RunTimeException的崩溃。小渠道验证的确也收集到一些崩溃,说明是起到捕获异常的作用。
捕获到异常后,只会将出错的页面关闭,而不会影响到App,再结合完善的监控系统、报警机制,终将带给用户极佳的体验。
思考
安全模式探索与实践的历程也经历坎坷、备受挫折,需要足够的延迟满足感。团队一直坚持不懈,完成每一次的挑战,为安全模式顺利上线做出了最大努力,且后续还会加油持续做的更好。
以下也带来我们的继续思考:
- 安全模式的解决场景是否可以复用到其他特定场景比如:阅读器连续崩溃,更或者就像微博:对连续崩溃后的用户友好交互界面。
- 这个系统真正的意义在哪里?快速响应线上问题、提高用户体验。贯彻七猫的企业文化:对用户好一点。
总结
到这里所有的都完成了。总结一下,安全模式就是APP启动阶段的保护实践。七猫安全模式就是致力于解决APP启动阶段的崩溃等问题,同时具备配置中心、自主修复、动态修复、数据中心、测试五个方面的一整套启动保护的解决方案。
欢迎加入我们!
目前团队 Android 与 iOS 岗位还有空缺,欢迎优秀的人才加入我们的团队,一起搞事情。
内推邮箱地址:yuminhua@qimao.com