项目核心技术点总结

224 阅读6分钟

最近接触到的一个千万日活的闹钟类项目,发现蛮多有意思的黑科技,特此记录一下。

1、APP保活拉活

1.1 多进程保活

正所谓,活着才有输出!

当我们的应用被用户划掉的时候,系统在几十毫秒到几秒内会保留进程当前的状态,在这个时间内,如能重新拉起进程,即可做到进程的保活。基于以上理论,我们可以做出以下尝试:

image.png

如上图所示: 为保证进程的存活几率,我们启动3个Service去创建3个进程(包括main进程),简单介绍一下工作流程:

  1. Service1配置在主进程,绑定Service2
  2. Service2配置在进程1,绑定Service3
  3. Service3配置在进程2,绑定Service1
  4. 三个Service同时对三个文件file1,file2,file3加锁
  5. 启动一个java进程java_process,在该进程中,主线程通过轮询给file1加锁,子线程t1给file2加锁,子线程t2给file3加锁,轮询间隔为500ms,正常情况下,都无法加锁成功
  6. 一旦出现某个file被加锁成功,则说明持有该文件锁的进程被销毁了,java_process通过binder重启对应的Service,从而达到唤醒进程的目的
  7. 3个Service互相拉活,从而拉活整个APP

1.2 前台通知常驻通知栏

APP启动的时候,启动前台服务,挂载一个前台通知,搭配上述的多进程保活,把通知绑定到Service1,实现前台通知的常驻,进而提升进场的优先级,避免进程被回收。

局限性: 1、安卓12之后,启动前台通知会有意想不到的崩溃,不一定能开启成功,可以采用workmanager方案替代前台服务。 安卓12前台通知适配官方说明

2、安卓13之后,默认不会授予通知权限,部分用户不会主动开启,为保证功能正常运行,采用媒体类通知替代普通通知,媒体类通知有豁免权,无需授权就可使用,从而实现前台通知的正常展示,此外,这个方案,还带来了其他收益,下面再讲。安卓13引进运行时通知权限

1.3 一像素Activity

监听锁屏就唤起该Activity,开屏就销毁,可以让APP在息屏阶段存活几率高一点。

局限性: 安卓10之后,限制后台唤起Activity,只能作用于10以下的机子,小米手机限制版本会更低,因为它修改了后台启动限制(出于商业化的目的),不过还是有办法可以绕过,后面会提到。

1.4 桌面Widget

通过引导用户去设置桌面小组件,给小组件配置定时刷新逻辑,让系统定期拉活应用。

1.5 账号同步

通过手机的账号信息同步功能,也能给拉活APP带来一定的收益。

1.6 权限引导

针对不同机型,通过截图或者直达某权限设置页,引导用户开启权限,调整电池管理策略,后台运行策略等,来达到保活的目的。

1.7 静态广播

Android 8开始,系统禁止注册大部分静态隐式广播,但是仍然有部分系统广播被豁免,通过注册这些被豁免的静态广播,在收到广播时拉活应用。隐式广播豁免说明

1.8 FCM空消息拉活

服务端每天定期给存量用户通过fcm发送data类型空消息,尝试让fcm拉活应用进程。

2、后台拉起页面实现

由于产品的特殊性,作为一个闹钟APP,在闹钟到达的时候,需要展示我们的专属闹钟页,由于我们是个工具类APP,用户大概率是不会长期停留在应用内交互,APP在后台是不可避免的重要的场景。

前面提到,安卓10之后,系统限制了从后台拉起Activity,除非用户去设置页开启权限,否则,只能在某些豁免场景中唤起。豁免场景

2.1 设置精确闹钟

通过设置精确闹钟,在精确闹钟到达时,拉起闹钟Activity,可以得到豁免。

局限性:

  • 这个豁免不一定是百分百生效,通过线上的实验组对比,发现开启了之后确实拉起成功率比之前高。
  • Android12开始,精确闹钟权限不是默认授权的,没权限情况下设置精确闹钟会导致崩溃,设置前需要判断是否获得权限。

2.2 开启悬浮窗权限

开启悬浮窗权限后,将允许后台唤起Activity,这个方案成功率最高,除了个别机型不生效,这个权限可以做成引导用户去开,默认是不开的。

2.3 通知配置FullScreenIntent

在通知创建的时候,可以配置FullScreenIntent,在部分机子会在通知到达的时候,同时唤起Intent指定的Activity。(PS:前面提到的媒体类通知替代普通通知,也可以配置FullScreenIntent,正是因为有了通知替代的方案,刚好弥补了下这个方案的不足)

局限性: 1、安卓14之后,FullScreenIntent的使用需要动态申请权限。

2.4 moveTaskToForg

如果APP还在系统的任务栈,通过移动应用到栈顶,使应用到前台,再从前台拉起Activity。经过实验验证,采用连续仿佛调用,可以提高拉到前台的概率。

2.5 快速重试startActivity

在后台唤起APP页面的时候,一次start不行,可以尝试到短时间内连续start,也有一定概率能拉起,不过比较玄学,不靠谱。

2.6 hook小米系统唤起页面的Intent,绕过后台启动activity限制

该方案仅对安卓10以下的小米机子有效。前面提到了,小米在安卓10以下,还加了自己的后台唤起APP权限,通过hook掉startActivity的Intent,通过反射拿到Intent里面的mMiuiFlags,令

mMiuiFlags |= 0x2

即可绕开后台启动的限制。

3、结语

以上方案已经在项目中落地,也在线上验证过是可行的,很多方案单从代码层面,是没法分析出是否可行的,但是实践告诉我们,它们是行的!