最近接触到的一个千万日活的闹钟类项目,发现蛮多有意思的黑科技,特此记录一下。
1、APP保活拉活
1.1 多进程保活
正所谓,活着才有输出!
当我们的应用被用户划掉的时候,系统在几十毫秒到几秒内会保留进程当前的状态,在这个时间内,如能重新拉起进程,即可做到进程的保活。基于以上理论,我们可以做出以下尝试:
如上图所示: 为保证进程的存活几率,我们启动3个Service去创建3个进程(包括main进程),简单介绍一下工作流程:
- Service1配置在主进程,绑定Service2
- Service2配置在进程1,绑定Service3
- Service3配置在进程2,绑定Service1
- 三个Service同时对三个文件file1,file2,file3加锁
- 启动一个java进程java_process,在该进程中,主线程通过轮询给file1加锁,子线程t1给file2加锁,子线程t2给file3加锁,轮询间隔为500ms,正常情况下,都无法加锁成功
- 一旦出现某个file被加锁成功,则说明持有该文件锁的进程被销毁了,java_process通过binder重启对应的Service,从而达到唤醒进程的目的
- 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、结语
以上方案已经在项目中落地,也在线上验证过是可行的,很多方案单从代码层面,是没法分析出是否可行的,但是实践告诉我们,它们是行的!