安卓收得到、苹果收不到,先别改代码。按通道、证书环境、用户授权三处查,每处都有五分钟能做完的验证。三处都对还收不到,再看内容与系统设置。
寄快递也是三件事:地址对、快递公司对、收件人愿意收。少一样,包裹就到不了。推送比寄快递多一层,收件人还分苹果和安卓两个体系。
推送通知是服务器主动把消息送到手机,不靠用户打开应用。链路有三段:你的服务器、苹果或厂商的推送服务、用户的手机。任何一段断了,消息都到不了。
先把三处摆出来,再逐个验。
| 查哪处 | 具体查什么 | 五分钟验证 |
|---|---|---|
| 通道 | iOS 是否走 APNs,安卓走厂商通道还是自建长连接 | 后台分平台看发送记录,iOS 是否为 0 |
| 证书环境 | 连的是沙箱还是生产,证书是否过期 | 看服务端配置的域名,看安装包来源 |
| 授权 | 系统通知权限、微信订阅状态 | 手机设置里看开关,后台看订阅返回值 |
顺序有讲究。前两处你能自己查,第三处要用户配合。所以先查自己这边,别一上来就让客户截图。
第一处,通道。
苹果只有一条路,APNs,也就是苹果推送服务。你的服务器把消息交给苹果,苹果再送到设备。没有第二条路,也不允许应用常驻后台自己收。
安卓在国内主要靠厂商通道。小米、华为、OPPO、vivo 各自有一套系统级推送,应用被系统清掉也能收到。极光的文档把这叫离线推送,接入时要单独申请各厂商参数,集成对应 SDK,也就是厂商提供的开发包。
安卓还有两条腿。厂商通道负责应用被杀之后的消息,自建长连接负责应用活着时的实时性。只接了一条,覆盖就不全。
同一款 App 在不同厂商后台要各注册一次,参数不能通用。少注册一家,那家手机就收不到。
这就是第一个不对称。iOS 只有一个通道,安卓有好几个,每个还要一套参数。哪一套没配好,对应的那批手机就收不到。
验证看后台。iOS 和安卓的发送量、到达量要分开统计。安卓正常、iOS 一直是零,多半是根本没走 APNs,或者走了但每次都被拒。
苹果提供了一个 Push Notification Console,可以绕过自己的服务端,直接对一台设备发测试通知。这条能通,说明证书和设备都没问题,毛病在你们的服务端。
iOS 的请求头也有硬要求。iOS 13 以后每条推送都要带 apns-push-type,标明是提醒还是后台更新。缺这个头,苹果直接拒,错误信息还不太直观。
还要认识设备令牌。它是苹果发给这台设备这个 App 的一串地址,重装、恢复备份、换机都会变。后台存着旧令牌,发出去就是石沉大海。
第二处,证书和环境。
苹果有两套环境,开发一套、生产一套,地址不同。测试连 api.sandbox.push.apple.com,正式连 api.push.apple.com,端口都是 443。
两套的证书和密钥不通用。拿开发证书连生产地址,苹果直接拒;反过来也一样。这是「安卓能收、苹果不能」最常见的原因,因为安卓的厂商通道没有这个双环境概念。
验证只要看一行配置:服务端连的是哪个域名。再看安装包从哪来:Xcode 直接跑真机是开发环境,TestFlight 和 App Store 是生产环境。
这里有个坑。TestFlight 的包看着像测试,实际走生产环境。不少团队拿 TestFlight 验收,服务端还连着沙箱,结果一台都收不到。
证书这块有个变化。早年用推送证书,一年到期要换;现在苹果推荐用密钥方式,密钥本身不设过期,但一个账号只能下载一次。
不管用哪种,都要有人管到期日和备份。证书过期不会提示用户,只在服务端返回错误,等到用户投诉已经晚了。
换了开发者账号或应用标识(Bundle ID),旧令牌基本作废。看着只是改了个名字,实际等于所有设备要重新注册一遍。
第三处,用户授权。
前两处都对,还得用户点头。iOS 第一次请求通知权限会弹窗,用户点了不允许,系统就记住,之后不再弹。
苹果的文档写得很直白:第一次请求后系统记录结果,后续请求不再弹窗。所以代码里反复调用没用,只能引导用户去设置里打开。
验证在手机上:设置 → 通知 → 你的 App,看「允许通知」开没开。关着的,服务端发得再对也到不了。
先分清发的是 App 推送还是小程序订阅消息。两者的通道、授权、失败原因全不一样,混在一起查会绕远路。
小程序是另一套。微信的订阅消息要用户主动点击才能弹订阅框,用户选 accept 才算订阅,选 reject 就是拒绝。一次调用最多订五条模板。
订阅还分一次性和长期。一次性订阅,用户同意一次只能发一条,发完要再要。这是产品设计问题,不是技术故障,很多「iOS 收不到」其实卡在这里。
后台能查状态。接口返回三种值:accept 同意、reject 拒绝、ban 被封禁。ban 最容易被忽略,用户投诉过或者平台判定骚扰,就会被封。
还有个隐形开关。用户勾了「总是保持以上选择,不再询问」,下次调用不弹窗,沿用上次的选择。要改只能去小程序设置页手动改。
三处之外还有两个小项,顺手看一眼。一是专注模式、免打扰、通知摘要,会把通知压后或折叠。二是消息内容不合法,标题为空、体积超限,苹果会直接拒收。
静默推送另算。它靠 content-available 唤醒应用,不显示横幅,用户强制退出应用后就收不到。拿它测「有没有收到」,很容易误判。
排查按成本从低到高。先看后台失败码,再看环境地址,然后核设备令牌,最后找用户确认授权。前两步十分钟,后两步要人配合。
失败码能说很多。BadDeviceToken 是令牌不对或环境不匹配,Unregistered 是用户卸载了,TooManyRequests 是发得太猛被限流。这三个词拿去搜苹果文档,都有解释。
让对方提供三样:设备令牌前八位、发生时间、手机型号与系统版本。有这三样,对着服务端日志能定位到具体一条,不用猜。
监控要按平台分开。合成一个「推送成功率」,iOS 挂了三天也看不出来。分平台、分环境、分消息类型,三条曲线放一起看。
上线前记四行:iOS 用生产地址、证书没过期、令牌是新的、用户已授权。安卓另算,厂商通道参数和自建通道都要单独测。
最后一句话。推送是三方协作:你的服务器、苹果或厂商、用户的手机。任何一方说不,消息就到不了。排查就是逐个问,谁说了不。





