关闭 Android 推送机制的一些看法和脑洞

2023-06-02 06:53:49 +08:00
 liyafe1997

一直以来 Android 的消息推送和后台机制都是一个值得诟病的事情,哪怕到了 2023 年,到了 Android13 。

哪怕是 FCM ,也极为依赖 App 的后台机制,需要 App 保持在后台运行,在内存里存在进程,FCM 才能正常推送,如果把后台完全压死(强行停止),那 FCM 是完全没法工作的。哪怕是 FCM 所谓的代推机制也是如此,本质上还是由 App 进程推送出来的通知。

因此,许多 App 其实只是用 FCM 来拉起 App 的 Callback 函数(以微信为代表),FCM Payload 不含消息内容,而是 App 收到 FCM 拉起后,再去轮询服务器。

甚至 Google 自家的 Gmail App 都是这么干的,而且还依赖 Android 的同步机制,似乎是由 FCM 触发同步机制,把邮件同步下来后才弹出通知。如果把 Android 的同步开关关掉,Gmail 直接不推送新邮件,这 FCM 推了个寂寞嘛。

因此,如果把 iOS 设备和 Android 设备上的 Gmail App 登录同一个帐号,然后给它发邮件,你会发现永远都是 iOS 设备瞬间亮起显示通知,而 Android 设备总是慢这么几拍,快则数秒,慢则数分钟才显示新邮件通知。

这也是 Android 后台耗电 /占用系统资源 /卡顿的根源之一,特别是类原生安卓 & 国际常用 App ( Facebook, Instagram, Twitter, WhatsApp, Telegram 等等)。虽然新的 Android 出了一系列后台机制,限制了很多活动,但哪怕在 FCM 下,这些 App 至少都要保留进程(“运行状态”)。更何况他们是有权执行代码占用 CPU 的,虽然会有限制。

再怎么限制后台活动限制 App 资源,还是和 iOS 有本质的区别,iOS 下再多 App 对系统也没有影响(只要你的空间足够),因为把 App 从后台推掉后,是完全没有机会运行的(那个后台 App 刷新机制另当别论),就跟 Windows 里,你下载了一堆 EXE ,不运行不会占用系统任何资源,只是一堆文件罢了。

倒是近几年的国产 Android & 国产 App 在这方面做得不错,各家厂商有自己的完全实现代堆的机制( mipush ,华为 push ,vivopush 等等),然后国产安卓的后台机制基本上是把 App 从后台推掉后就完全压死了(强行停止状态),各种 broadcast 都收不到,别的 App 也拉不起(国产 Android 还专门限制了链式拉起)。各家 push 则是实现了类似 iOS 的代堆,完全不依赖 App 的代码本身,不依赖后台,由系统服务代显示通知。

(顺便说个小玩意,一个 Xposed 模块,叫 fcmfix ,这个在国产安卓上配合 FCM 工作得相当好,能让 FCM 推到压死后台的 App 上,原理是在收到 FCM 时,先把 App 拉起。虽然最后也要拉起 App ,但至少在 App 没有收到消息之前没有后台活动)

既然这个问题从 Android 诞生之日起就是一个非常诟病的问题(特别是 Android2.x/4.x 时代,群魔乱舞各种牛鬼蛇神 App 互相保活就为了保持 push service 长连接,和系统和用户斗智斗勇,导致那几年安卓是卡顿的代名词),而且无论 GCM/FCM 还是现有的各国产安卓 push 机制都有一个问题:这毕竟是一个云服务,对于一些场景,比如企业内网 /本地化部署的应用,就没法上这些“云服务系统级 Push 了”,这类应用的客户端也只能长驻后台,自己维护一个长连接。根据 Android 的电源管理指南,这种情况需要加入电池优化白名单中,也就是应用的后台活动不受系统限制,才能保证消息推送的及时。

也就是说,作为一个开源且开放的操作系统,Android 本身并没有一个解决方案来解决这个问题,但这个问题在移动设备上确实是个能覆盖绝大多数应用场景的问题。

脑洞来了:

为何 Android 不实现一个系统级的,不依赖 App 后台活动的消息推送 & App 拉起 Callback 的协议?假如 Android 实现了这么一种协议,这个协议是开放的,你可以自己编写服务器端(当然 Google 也可以提供一个参考实现),部署在自己的服务器上,然后 App 往 Android 系统注册一个长连接(指定你的服务器 URL ),由 Android 来维护这些长连接( KeepAlive ),注册之后就与 App 无关了,完全由系统接收数据,哪怕把 App 完全退出后台压死,消息也可以由系统代推,并且支持某种消息,能把 App 拉起并把 Payload 传给 App 处理(应用场景如音视频通话,把 App 的 Activity 拉起来弹出通话 UI 并响铃)。

虽然还是每个 App 一个长连接,但是这个长连接是由系统管理的,个人感觉哪怕装了几百个 App ,就算保持几百个 TCP 连接并不会带来太多的开销,且 App 的后台可以完全压死,不占用任何 CPU 和内存资源。而不是像安卓 2.X/4.X 时代各家 App 都运行一个“PushService”,除了维护长连接之外,还东搞西搞占用 CPU 和内存资源。这样也有助于内网 /本地化部署的企业应用能用上规范的,系统级的推送功能。

11465 次点击
所在节点    Android
22 条回复
jiagm
2023-06-02 07:11:03 +08:00
Android Gmail 的推送确实是玄学,有时候和 iOS 同样快,有时候就得等好长时间。以前在 Reddit 看到说 Google 的工程师认为邮件并非实时交流工具所以不需要实时推送,不知是真是假。
RightHand
2023-06-02 07:25:47 +08:00
fcm 支持直接推送的,但是是标准的格式化消息,往往 app 希望的是自定义化的通知信息,这就导致了 app 必须拉起来构建绘制内容。说到底还是留了口子没做绝
xiadong1994
2023-06-02 07:35:56 +08:00
@jiagm #1 有点扯淡,GMail 网页和浏览器通知就是实时的。
1821015428lqy
2023-06-02 08:34:47 +08:00
安卓 ios 双持 安卓刷了 fcmfix 模块 每次通知两边都能同时收到 (国产 rom 上的 fcm 推送好像是个残血,会被系统压住)
NaiveSimpleYoung
2023-06-02 09:50:55 +08:00
完全可以写一个 app 来保持你所说的长连接,各国产 ui 的推送不就这么干的吗,何必绕那么大个弯子
NaiveSimpleYoung
2023-06-02 09:53:13 +08:00
另外 fcm 推送需要应用进程吗被杀死,这是这套推送系统的设计者有意为之:非不能也,不为也。
NaiveSimpleYoung
2023-06-02 09:53:52 +08:00
*吗被杀死--> 没被杀死
wy315700
2023-06-02 10:00:55 +08:00
因为 push 的重点根本不在接口。。在于云服务!!!
统一推送联盟死掉的原因也正是因为如此,他拿不出钱来建设如此庞大的推送服务。

另外

> 就算保持几百个 TCP 连接并不会带来太多的开销

心跳包都能耗死你
sentinelK
2023-06-02 10:08:23 +08:00
“哪怕是 FCM ,也极为依赖 App 的后台机制,需要 App 保持在后台运行,在内存里存在进程,FCM 才能正常推送”

不太理解这句话。

如果说的是 Notifications Composer ,并不依赖 app 进程。都是通过唯一 ID 进行系统级别的下发,然后直接唤出 notification 功能。点击后可以携带参数,app 在根据当前的生命周期进行逻辑响应(唤醒、调出对应业务界面等等)。

反之如果是数据消息(国内推送往往叫“透传消息”),确实需要应用保活,因为需要 service 处理传递过来的字符串,但这并不是一个常见的场景。因为需要 service 或者 app 加工时,app 也往往在活动中。
sentinelK
2023-06-02 10:15:49 +08:00
总结:

如果是异步场景(收到一条消息、邮件,或者是提醒等等),app 没必要及时响应,也就没必要弄透传消息,也就没必要 app 保活。用通知消息足矣。

反之,如果是即时响应的推送,那么 app 理论上讲 app 也必然在前台保持活跃。

所以我个人理解,目前 Android 的推送逻辑是没问题的。
hellomynameis
2023-06-02 10:31:59 +08:00
@sentinelK #10 我的体验类似,Instagram 、Twitter 这些软件限制后台活动都没有正在 Activities 运行,也没有设置 Wakelock ,也没有开启安卓的账户定时 Sync 功能,依然可以通过 FCM 推送异步场景的通知。测试环境为原生系统。感觉 OP 说的 FCM 可能跟我说的这个 FCM 不是一个 FCM ,此 FCM 非彼 FCM 。
wy315700
2023-06-02 10:34:25 +08:00
@hellomynameis
@sentinelK
他说的应该是 FCM 无法拉起被 force stop 的应用
sentinelK
2023-06-02 10:38:13 +08:00
@hellomynameis 我能想到的唯一场景就是有的 app 不愿意使用 notification 来承载内容,也不希望过度使用自己的服务器性能,从而只是通过数据推送(透传消息)来让用户的手机客户端判断 notification 是否应该显示,以及应该显示什么。

但这属于对客户端性能的一种滥用,并不值得推崇。
hellomynameis
2023-06-02 10:39:42 +08:00
@wy315700 我刚才又测试了一下,的确,一个在通知中心里有通知记录的应用,我强行停止以后通知就自己消失了。这是一个有点弊端的设计,原生安卓应该是设计成了不显示任何已经强行停止(相当于国内的上滑)的 APP 的通知,这一点如果优化的话使用体验和电池续航会好一些。

不过在我的实际使用过程中,这些没有被强行停止也没有设置 Wakelock 的应用,后台电池消耗很微小
iovekkk
2023-06-02 11:18:25 +08:00
问题不在于谷歌有没有提供你想要的机制
而是在于这些 app 服务商都想让自己的进程永远运行在后台
而恰好他们发现了能实现的方案
archxm
2023-06-02 18:04:17 +08:00
未来真的可能人人都是产品经理了。
每个使用手机的人,都需要花钱购买云服务,比如 fuction 计算,存储服务,长期存储,预测,模型训练。再稍微懂点前端。
未来的 2b 型 app 开发商估计都挣不到啥钱
shuianqingfeng
2023-06-02 22:30:20 +08:00
歪个题,金融类的 push notification 都有阅读实效性,一般堆 5-8 个消息的话,后面来的通知就会冲掉前面的通知。
iOS 就不会,我可以一天堆叠着一起看掉

这方面有什么办法解决吗?论操作效率还是比较喜欢国内安卓比如 miui
doruison
2023-06-04 11:19:44 +08:00
@hellomynameis 我记得很多年前(可能有十年了)有人在开发者大会问过谷歌,谷歌的回复是既然你都手动关掉了,那就说明你很讨厌这个软件,他的推送不仅不重要而且可能是有害的……
也就是说这不是一个 bug 而是 feature ,他们设计上就是如此,你关心的程度(打开关闭的频次和时间)显示应用的重要性,重要性决定什么时候推送
willwon1
2023-06-04 12:23:16 +08:00
安卓系统上各种的不好用 本质上都是各种的妥协 在可预见的时间范围内这些妥协无法被解决 twitter facebook telegram 的推送永远在国内无法使用,手机上如果安装一个 tg 要是想使用的方便必须要挂上 VPN+常驻后台, 带来的电量损失性能损失 都只能通过厂商堆叠内存 增加电池容量增加重量 最终由用户买单解决 这也是为什么 ios 可以用 6GB 的内存做到安卓 16GB 内存都流畅的原因 与其说是各种流氓应用 倒不如说是系统层面的 国家政府政策的问题 IOS7 成的市场占有率不是没有原因的 并且这个问题再可预见的时间内都是无法解决的
换 IOS 解君愁 否则任何的推送机制的改变都是无法解决的 除非有一天墙塌了 或者中国形成了统一的推送大联盟

打开淘宝的安装包,看看里面的用户协议,mipush 华为 push vivopush 一个安装包内为了兼容各个厂商,同时接入 5 个以上的 push SDK 这是合理的结果吗?
NokiaForever
2023-06-26 18:10:47 +08:00
@sentinelK 想要应用接收 fcm 后在通知栏显示通知,必须有自启动权限,fcm 日志里可以看到,有自启动权限的才能 Successful Broadcast ,否则是 Failed 。三星手机想要接收 fcm 就必须允许自启动,而且国行 rom 做了限制连不上 Google 就断开 fcm ,国行默认(除了微信 QQ 几个)都是把 app 的电池优化改限制,国际版则默认都是优化,因此国行得开自启动并且一直访问互联网才能使用 fcm 。我研究过了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/945081

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX