App 明明没打开,为什么还能收到消息?

0 阅读9分钟

第四生产力 · 程序员眼里的世界

App 明明没打开,消息却照样弹出来。很多人的第一反应是:它是不是一直在后台偷偷运行?

有这种可能,但仅凭一条通知,还不能下这个判断。因为接收消息的,未必是这个 App 自己。

要解释这件事,先得分清:App 的页面、手机系统和远端服务器,各自负责什么。

页面关了,哪一部分还在工作?

以外卖配送提醒为例。下面只用它说明机制,不代表某款产品的具体实现。

你下单时,订单交给了远端的业务系统。以后商家接单、配送状态变化,都可以先记录在那里。你回到桌面,关闭的是眼前的页面,并没有顺便关掉处理订单的服务器。

但这只解释了一半:服务器知道订单变了,手机又是怎么知道的?

一种办法,是让 App 在后台维持连接,随时等消息。这种做法确实存在。所以,“没看见页面”也不能直接证明应用的所有代码都停止了。

不过,收到提醒并不一定依赖这款 App 一直运行。手机可以把接收推送的工作交给系统或平台服务,等消息到了,再按规则处理。

苹果的通知权限文档就明确说明,通知可以在应用未运行或处于后台时,通过提示、声音、图标角标吸引用户注意。

于是,判断要更谨慎一点:看到一条通知,不能单凭这一点认定 App 的主程序一直在后台忙。

谁替 App 接到了那条消息?

手机操作系统本身就要管理联网、通知和应用状态。平台提供的推送通道,可以接收来自云端的消息,再把它交到适当的位置。

苹果设备使用苹果的推送服务,叫 APNs。具有相应 Google 服务的 Android 设备,可以使用 Google 的消息服务 FCM。国内也有厂商提供自己的推送通道。

例如,华为对推送服务的机制说明中,提到利用系统持续的连接,在应用进程不运行时推送消息。这是相应平台的能力,不能据此保证每台手机、每款 App 都走同一条路。

把常见的可见通知简化一下:业务服务器把“订单状态有更新”交给推送平台;平台把通知送到手机;手机根据权限和展示规则,把提示放到通知栏或锁屏上。

显示一句提醒,不要求订单页面此刻也打开。

Google 的Android 接收文档也把这两件事分开:应用在后台时,通知型消息可以进入系统通知区;另外一些消息则需要应用代码处理。

这不是说应用绝不参与。不同消息可能触发不同处理,通知扩展也可能参与加工。这里只需要记住:显示通知,与把整个 App 持续打开,是两种不同的工作。

这么多手机,怎么知道该发给你?

推送平台当然不能把你的配送提醒广播给所有人。

应用要先完成登记,取得一个用于投递的标识,再把它交给自己的业务服务器。之后,服务器发送通知时,带上这个标识,平台才知道投递给哪个设备上的哪个应用。

可以把它大致理解成一份“投递地址”。但它不是你的手机号,也不是永远不变的身份证。

苹果的APNs 注册说明明确区分了设备与应用:同一台手机上的不同 App,不能直接共用同一个设备令牌;这个令牌也可能变化。

所以,“我今天没打开它”,与“它从来没有登记过”,是两回事。你之前使用 App 时,相关登记就可能已经完成。

这个地址也不等于通知权限。地址解决“送给谁”,权限解决“允许怎样提醒你”。平台还要求发送方具备相应认证和配置,并不是知道一个地址就能随便投递。

图片

顺着图看:配送变化先发生在业务端,提醒沿推送通道来到手机,系统在规则允许时展示。你点击之后,App 才可能打开订单页,并向业务服务器获取详情。

这张图画的是一种常见路径,不是所有通知的完整实现。提示里可以带一部分信息,但订单详情未必都装在那一条提醒里。

为什么不让每个 App 都自己等消息?

假如每款 App 都独自保持连接、检查新消息,手机就需要反复为这些后台工作使用网络和计算资源。

集中接收的价值,是把一部分重复的等待工作合起来。

Android 官方的省电机制说明写得很直接:FCM 提供共享的持久连接,需要实时消息的应用可以共用,减少各自维持单独连接的需要。

这里的“持久连接”,就是不必为每条消息都从头建立联系,通道在适当条件下保持可用。手机仍然要联网,也仍然要消耗资源;共享通道并不意味着推送完全不耗电。

我觉得值得记住的是这个取舍:每款 App 都希望自己的消息及时到达,系统则要兼顾整台手机的电量、网络和你的注意力。

推送服务是在协调这些需求。它也没有给每款 App 一张“随时随地运行”的通行证。

有通道,为什么有时还是迟到?

因为一条消息“发出去了”,可以指不同的事情。

业务服务器提交了请求,推送平台接受了请求,消息送到手机,系统显示了提醒,你注意到并读完——这些步骤不能合成一个状态。

FCM 的消息有效期说明就明确提醒:拿到消息编号,表示平台接受了投递请求,不表示手机已经收到。

手机没有连上通道时,消息可能暂存,等恢复连接再投递;也可能因为过期而被丢弃。部分提醒可以合并成更新的一条,不保证原样补发全部历史消息。

手机能联网,也不代表每条后台消息都立即处理。省电机制可能延后一些工作;应用代码需要更新内容时,还会受到后台执行规则约束。苹果也明确说明,用于后台更新的通知不保证送达。

还有一种情况:消息已经到设备,但系统按你的设置没有响铃、没有在锁屏显示,或延后提醒。

所以,我更愿意把三个问题分开查:消息有没有送到,通知有没有展示,人有没有看到。只盯着“服务器说成功了”,很难知道问题卡在哪里。

那我把它划掉,为什么还不安静?

返回桌面、划掉最近任务中的卡片、在设置里强制停止、关闭通知权限,并不是同一个操作。

返回桌面主要改变你正在看的页面。划掉卡片会怎样影响应用,取决于系统和厂商策略,不能统一理解成“从此拒收它的提醒”。

设置里的强制停止则是更强的状态变化。以 Google 的FCM 接收说明为例,Android 用户在设备设置中强制停止应用后,需要重新打开应用,消息接收才会恢复。

同一文档对 iOS 也有退出后的限制,但限定的是后台消息,不能扩大成“所有可见通知都会停止”。讨论“关掉 App”时,把具体操作和消息类型说清楚,答案才不会互相矛盾。

如果你的目的只是减少打扰,更直接的入口通常是通知设置。

Android 13 及以上对普通非豁免通知设置了权限控制。iPhone 也可以调整通知位置、声音、锁屏预览和提醒时间。具体入口和名称随系统、机型而异。

你可能想保留配送更新,却不想收促销;如果 App 提供分类订阅,可以在应用内区分。没有这样的选项,就需要在保留业务提醒与减少整体打扰之间做取舍。

如果担心旁人看到锁屏上的内容,可以限制预览。通知仍可能到达,但敏感文字不必直接展示出来。

不过,关闭通知并不等于让服务器停止处理订单,也不等于让应用从此断网。反过来,能收到通知,也不足以证明它在监听你。要判断数据访问,还要查相关权限和实际行为。

本文讲的是从服务器送来的远程通知。日历等工具还可以提前登记本地提醒,不需要每次等服务器来发消息;不能把手机上的所有提醒都套进同一条链。

下次别只盯着“它开没开”

回到那份外卖:页面退出了,业务服务器还在处理订单;手机的接收通道也可能仍然可用。配送提醒到来时,系统可以先把消息展示给你,不必等你一直守着订单页面。

手机里的一款 App,看上去只是一个图标,背后却可能有几个分别运行的参与者。把它们分开,很多现象就容易理解了:页面没开仍能提醒,提醒出现后详情还要加载,清掉卡片也未必能阻止下一条通知。

下次有一款 App 总让你分心,可以先打开它的通知设置,决定哪些消息值得保留、哪些内容不该出现在锁屏上。与其反复猜它有没有“偷偷开着”,先控制你真正想改变的那一环。

——第四生产力 · 程序员眼里的世界

—— 第四生产力 ——

专注企业级 AI 工程实践

RAG|Agent|推理优化|集群调优

从模型能力到业务价值的最后一公里。