ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

App推送机制全解析:从APNs到厂商通道的实战避坑指南

App推送机制全解析:从APNs到厂商通道的实战避坑指南 其实做App推送这件事我刚入行的时候觉得特别简单不就是调个接口发个通知嘛。直到自己完整做过几个带推送功能的上线项目才明白这玩意儿水有多深。光是一个消息送达率就能让开发、运营、产品吵一整轮。这篇内容不搞花架子把我这些年踩过的坑、摸清楚的逻辑一次讲明白。无论你是刚接手推送模块的客户端开发还是要做推送运营后台的产品经理或者是想搞清楚推送原理的测试同学照着这篇梳理能省下不少弯路。先说清楚一个最容易被混淆的概念推送到底是什么。简单来说推送是服务端主动向用户设备发起消息传递的机制不需要用户主动打开App也不需要客户端反复轮询。它和拉取是两种相反的通信模式。没有推送之前App想知道服务端有没有新数据只能定时去问这不仅费电、费流量而且不实时。推送解决了这个问题服务端有话说的时候直接找到用户手机把话说出去。但这件事在移动端做起来远比想象中麻烦尤其是Android生态简直是大坑套小坑。1. 推送的本质和它解决的现实问题1.1 推送的本质服务端主动找上门在技术层面推送依赖于一条常驻的系统级长连接。iOS和Android系统各自维护着这样的连接通道应用服务商把消息交给系统通道系统再转发到具体设备上。这意味着真正负责消息下发的不是App自己而是操作系统。这带来一个非常关键的隔离效果即使App进程被用户滑掉、系统杀了进程只要系统通道还在通知依然能到达。这里有个很生活化的类比。App像你家里装的对讲机系统通道像小区的门卫室。你有事联系住户不需要跑到每栋楼下喊直接告诉门卫室门卫室再用内部广播通知。即便住户正在睡觉没接对讲机门卫的广播依然能把他叫醒。推送就是这个门卫广播。搞清楚这个本质你就能理解很多现象为什么Android手机关掉App后台后还能收到通知因为通知是系统转发的不是App发的。为什么用户强行卸载或者彻底关闭通知权限后收不到了因为门卫室被住户下了拒收指令。1.2 为什么短信和站内信替代不了推送不少业务方一开始会问我有短信通道也有站内信为什么还要接推送这三种触达方式解决的是完全不同的问题。短信的优点是覆盖面广、不需要App存在、穿透力强但成本高、限制多、用户反感度高。站内信本质是用户来你家时才能看到门口贴的条适合承载需要用户主动查看的历史记录比如账单明细、系统公告。推送的定位则是实时提醒低成本触达适合高频、即时、轻量的消息场景。我做过一个运动类App它的业务形态就很典型用户设置了每日锻炼提醒、好友发起了运动挑战、教练安排了训练计划这些都需要实时通知。用短信提醒显然会把成本拉到天上用站内信又完全起不到提醒作用。推送是唯一合理的选择。这也是为什么社交、电商、工具、运动、网约车这类App全都重度依赖推送——它是产品与用户保持连接的生命线。1.3 推送的核心指标按消息类型分开看很多团队一上来就谈送达率要100%这其实是个伪命题。推送消息至少要分成三类每一类的目标完全不同营销类消息比如电商大促、优惠券到期这类消息天然容易被用户屏蔽送达率能到80%以上就算不错。服务类消息比如订单状态变化、物流轨迹、验证码这类消息用户是期待收到的送达率应该目标逼近100%。系统类消息比如账号异地登录提醒、版本强制升级这类消息即使部分Android机型有厂商限制也必须有兜底方案。理解了分类你才能正确看待技术方案选型。如果所有消息都要求最高可靠性那技术成本会成倍增加比如需要同时接入厂商通道自建长连接短信兜底。但大多数产品根本不需要这么重的方案。2. 国内App推送的生态与选型为什么Android这么乱2.1 iOS的APNs与Android海外的FCM两条标准路线在iOS平台上推送几乎是唯一解APNsApple Push Notification service。所有iOS设备的通知都走苹果的统一通道。优点是极其稳定、省电、体验统一缺点是所有消息都要经过苹果审核机制且无法像Android那样随意发透传消息静默消息限制较多。在Android海外市场Google的FCMFirebase Cloud Messaging扮演着类似APNs的角色。但由于国内设备上没有完整的Google服务依赖FCM这条路在国内走不通。这就导致了国内Android推送生态进入了一种分裂状态。2.2 国内厂商通道小米、华为、OPPO、vivo、荣耀既然没有统一的系统通道国内头部手机厂商各自建立了自己的推送通道。现在主流的有小米推送MIUI、华为推送HMS Push、OPPO推送ColorOS、vivo推送、荣耀推送。魅族也有一套但市场份额小很多第三方服务商也兼顾。为什么你必须接厂商通道因为国内Android手机上很多用户有清理后台的习惯App进程随时可能被杀。如果只靠App自己维持长连接进程一死推送就断了。厂商通道是系统级的即使App被杀系统依然能接收并展示通知。实测下来应用商店分发的主流型号厂商通道的实时性和可靠性远好于自建长连接。这就像一个城市没有统一邮政系统每个小区厂商都有自己的快递柜。你要给全市住户送通知就得挨个小区谈合作把包裹放进每个小区的柜子里。这也就是为什么国内推送集成工作比iOS繁琐得多。2.3 第三方推送服务商极光、个推、友盟、MobPush面对这么多厂商通道逐家对接显然不现实。常见的做法是通过第三方推送服务商比如极光推送JPush、个推、友盟推送、MobPush。这些服务商已经提前把小米、华为、OPPO、vivo等厂商通道全部封装好你只需要接入一个SDK就能把消息同时下发到不同厂商通道。第三方服务商的核心价值有两个统一接入和智能路由。前者很好理解后者是指服务商根据设备的厂商类型自动选择合适的通道下发不用客户端自己判断。比如同一台小米手机服务商会自动调用小米通道而不会走FCM或者自建长连接。选第三方服务商的时候我建议重点考察几个点厂商通道的覆盖度是否支持最新的荣耀、是否有魅族、免费额度和商务条款、控制台的运营功能定时推送、标签分群、A/B测试、API的扩充能力以及出问题时的技术支持响应速度。提示很多团队一开始为了省钱自己对接厂商通道结果光是要搞定vivo和OPPO的厂商申请资质就折腾了一个多月。如果你的业务不是特别在乎推送这个环节的差异化能力用第三方服务商是更理性的选择。2.4 Android与iOS推送机制对比速查对比维度iOSAndroid国内主流做法系统通道APNs统一通道厂商通道为主小米/华为/OPPO/vivo/荣耀消息类型通知栏消息为主静默推送受限支持通知栏消息和透传消息进程被杀影响不影响系统接管厂商通道不受影响自建长连接会断通知权限首次安装弹窗请求用户可拒绝Android 13开始需要运行时通知权限送达可靠性高依赖厂商通道接入和用户设置开发复杂度较低较高需要适配不同厂商SDK这张表基本概括了为什么推送这个小功能在不同平台上工作量和坑位差距巨大。3. 一条推送消息的完整生命周期从点击到展示3.1 推送下发的完整链路一条推送从业务服务器到用户手机大致经过五个环节业务服务器调用推送服务商的API传入推送内容、目标设备标识、过期时间等参数。推送服务商根据目标设备的类型和在线状态选择最优通道。通道服务器APNs或各厂商推送服务器将消息推送到目标设备。设备的系统级进程收到消息展示通知栏消息或根据消息类型触发App回调。App在合适的时机处理消息比如跳转页面、更新UI、上报点击事件。这里面任何一个环节都可能出问题。比较常见的坑是第一步传错设备标识或者第二步通道选择错误导致消息走了低优先级通道又或者第三步厂商服务器被限流。排查推送问题的时候要按这个链路逐段定位而不是只看为什么收不到这一个表象。3.2 通知消息与透传消息两种完全不同的玩法在Android生态里推送消息可以分成两种类型通知消息和透传消息。这个概念极其重要很多初期的项目就是因为没搞懂这两者的区别导致消息展示异常。通知消息是直接由系统展示的通知栏消息不需要App进程存活就能展示。用户看到的就是标题内容。这类消息是App被杀死后依然能提醒用户的关键但是不能控制消息的展示样式只能使用系统默认的交互。透传消息也叫静默消息消息到达设备后系统不会自动展示而是回调给App由App决定接下来做什么。比如App收到透传消息后可以自行弹一个自定义弹窗、更新数据、触发下载任务。但前提是App进程必须活着否则压根收不到。所以在实际项目中透传消息一般用来做应用在线时的业务场景比如IM消息、客服消息、实时价格更新。我见过有团队把所有消息都用透传发结果用户一杀进程就收不到关键通知被运营追着骂。正确做法是需要保证100%展示的消息走通知消息需要App处理逻辑的消息在App存活时走透传。更稳的方案是通知消息和透传消息同时发通知保证触达透传保证业务逻辑。3.3 离线消息用户关机、断网了怎么办推送服务商通常都有离线消息机制也就是当设备不在线时先把消息存下来等设备上线后再补发。这里有一个需要仔细设计的参数离线消息的有效时间。比如在离线时间默认是1天那用户断网一天后打开手机会瞬间收到一大堆过时通知体验非常糟糕。比较好的做法是区分消息类型服务类消息可以设置几小时的有效期营销类消息设置更短比如1小时有些时效性极强的验证码消息甚至可以直接不做离线补发。推送服务商的后台一般都有这个参数配置不要用默认值。3.4 打开发送的payload长什么样不管走哪个通道推送消息最终都会有一个标准化的payload结构。以iOS APNs为例核心字段如下{ aps: { alert: { title: 运动提醒, body: 你今天还有3公里目标未完成 }, badge: 1, sound: default }, custom_key: custom_value }Android厂商通道的payload结构虽然各不相同但核心概念一致包含通知的标题、内容、是否响铃震动、消息ID以及自定义的extra字段。开发中常见的坑是iOS端自定义字段如果放在aps外层App在后台时framework层能收到但如果App被杀点击通知启动App时只能从delegate回调里取出launchOptions这里面的数据解析特别容易出错需要认真测试。4. 接入推送的实操细节从App到服务端的必备功课4.1 申请各厂商通道的资质和密钥不管你是直接对接厂商还是用第三方服务商申请厂商通道都需要一些基本资质。通常你需要准备App在应用商店的上架信息或应用签名、企业资质或个人开发者信息。华为、小米、OPPO、vivo都有自己的开放平台申请流程相似注册开发者账号、创建应用、开通推送服务、获取AppID和AppKey/AppSecret。实操中容易卡壳的几个环节OPPO和vivo的推送申请对非上架应用审核较严有时要求提供软著或上架截图。建议在项目立项初期就同步申请不要等开发完了再补。华为的推送服务支持Debug模式但要注意区分调试和生产的ClientID。荣耀推送目前基本沿用了华为的推送接口但要在荣耀开发者平台单独创建应用。注意厂商通道的密钥是一对一的一个App对应一家厂商的一套Key。如果同一个App包名在多个渠道申请了不同的签名一定要确认屏蔽逻辑否则消息推送会互相串。4.2 第三方SDK的接入与初始化这里以常见的第三方服务商为例大致流程是在服务商后台创建应用、获取AppKey然后在客户端进行初始化。Android端在Application的onCreate里初始化JPushInterface.setDebugMode(true); JPushInterface.init(this);iOS端在AppDelegate的didFinishLaunchingWithOptions里注册[JPUSHService setupWithOption:launchOptions appKey:your_app_key channel:App Store apsForProduction:isProduction];初始化完成之后需要获取设备的registrationId并上报给服务端。服务端后续推送时靠这个ID定位设备。这里的常见问题是一个用户多台设备的情况设计注册信息时建议一张表里维护userId与多个deviceToken的映射关系并在登录态变化时及时解绑。否则用户换设备之后消息很容易发到旧设备上。4.3 Android 13通知权限绕不开的硬门槛Android 13API级别33开始通知权限变成了运行时权限需要像请求定位权限一样向用户申请。这一步被很多老项目忽略导致升级到Android 13后推送突然失效。申请核心代码如下if (Build.VERSION.SDK_INT 33) { val manager getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager if (!manager.areNotificationsEnabled()) { requestPermissions(arrayOf(android.permission.POST_NOTIFICATIONS), 100) } }只有在拿到权限后App才能展示通知栏消息。这个弹窗的时机设计很有讲究太早弹用户会拒绝太晚弹用户可能根本不知道这个App是干嘛的。我通常的做法是在用户完成一个关键操作后弹出并在弹窗前先展示一个自定义引导浮层说清楚开启通知可以收到订单状态、活动优惠等重要提醒能显著提升授权率。4.4 iOS端的证书与Key配置两个必须注意的环境iOS推送依赖APNs证书或Token Key。如果使用旧式证书需要注意p12证书会区分开发环境sandbox和生产环境production。开发阶段用开发证书发布后用生产证书如果环境配错推送在某种情况下可能静默失败。如果使用Token Key.p8文件则没有环境和证书有效期的问题Key有效期最长可达一年而且一个Key可以同时用于多个App是目前推荐的方式。无论哪种方式在交给服务端之后一定要在服务端保留好环境参数在推送接口里明确指定目标环境。4.5 服务端推送接口设计要点服务端是整个推送链路的发起方接口设计直接决定后续的可靠性。我总结的几个关键点消息队列解耦推送请求先进入MQ由消费者异步调用推送服务商接口防止业务接口因为推送超时被拖垮。幂等设计每个推送任务都要有全局唯一的任务ID服务商接口支持根据消息ID去重业务端也要做去重。回调上报必须接收并存储推送服务商的下发回执送达、点击、过期等状态这是排查问题的数据基础。内容审核对推送内容做敏感词过滤、链接检测尤其是营销类内容避免被封禁推送权限。限流控制每家服务商都有接口QPS限制高峰期需要做限流否则会有部分消息被丢弃。5. 推送运营后台内容、频控与用户分群5.1 推送文案怎么不招人烦推送是一个强打扰产品文案写得好不好直接影响卸载率。我自己看数据发现用户最容易点击的文案有两个特征一是明确表达了这条消息对他有什么好处二是没有营销轰炸感。比如差标题限时优惠全场5折好标题你收藏的跑步鞋降价了直降80元好的推送文案往往会在开头就交代清楚你是谁避免用户看到通知时皱眉回想半天。对于服务类消息直接把核心信息放标题里比如您的订单已到达请到前台领取用户不打开App也知道发生了什么这会极大地提升用户对App的好感。5.2 频率控制是底线工程推送频控如果做不好后面所有运营动作都会塌方。比较常见的做法是单个用户每日推送条数上限比如3条、同一类型的消息N小时内不重复发、营销类消息只在特定时间段发送比如10:00-12:00和19:00-21:00。这些控制既可以在服务端代码里做也可以在推送服务商的后台配置。更精细的做法是给用户打标签比如营销敏感用户、重度睡眠用户针对不同标签执行不同的频控策略。这个需求在项目初期可能没有但如果推送体量上来迟早要做。5.3 推送的A/B测试不要靠感觉推送文案、推送时间、推送人群都是可以A/B测试的。很多服务商后台已经提供了简单的A/B实验功能。实操中一次实验的样本量不要太小每个分组建议至少几万人否则结果没有统计意义。同时要区分核心指标营销推送看点击率和转化率服务推送看送达率和用户满意度。我做过一个电商类的实验同一批用户A组推送文案强调价格优惠B组强调库存紧张结果是B组点击率高出37%。这个结果如果靠直觉很难猜对。所以推送内容生产也应该是数据驱动的而不是灵感驱动。6. 常见问题与排障技巧收不到推送时别慌6.1 收不到推送的排查顺序收不到推送是出现频率最高的问题。我的排查顺序固定是通知权限 - 设备标识 - 进程状态 - 厂商通道 - 服务端日志。先看手机设置里App通知是否开启。Android用户很容易误关通知权限到时候怎么测都收不到。再看registrationId是否和服务端保存的一致App重装后registrationId会变化很多人忘记更新。再看测试机型有些厂商对自启动管理、省电策略有独立的开关即使用户打开了通知权限后台限制仍然能卡掉推送需要在系统设置里把App加入白名单。如果以上都没问题再看服务端推送日志确认消息是否已经推送到服务商、服务商返回的响应code是什么。第三方服务商的后台一般都有查询推送明细的功能能看到每条消息的送达状态排查效率会高很多。6.2 推送到达率低先看是不是用户自己关了推送到达率低很多时候不是技术问题而是用户主动用脚投票。当用户发现一个App总是发无用的广告他大概率会关掉通知。如果你发现自己App的推送送达率在持续下滑优先去检查用户对推送消息的点击率以及通知权限的开启率。这些数据在第三方服务商后台都有。如果确认技术链路正常那么问题很可能出在内容端。此时应该做的是重新梳理推送内容的价值感而不是继续加码推送次数。推送次数越多用户的授权率越低这是产品运营层面的恶性循环。6.3 App抓包看推送请求排查推送问题时抓包定位非常有帮助。尤其是服务端推送接口传参错误导致的静默失败光看服务端日志很难快速定位。可以抓两种包服务端HTTP请求抓包、客户端SDK与厂商服务的网络请求抓包。抓包工具方面常见的方案有Charles、Fiddler、Wireshark以及一些移动端抓包工具。需要注意很多厂商推送SDK默认不走系统代理需要额外安装证书并做SSL解绑。另外抓包时手机和电脑要在同一局域网部分厂商通道强制使用HTTPS证书校验抓包时可能会出现SSL握手失败之类的提示这并不一定是推送问题可能是抓包工具的证书没有被信任。6.4 测试阶段最容易忽略的机型兼容问题推送的兼容问题往往出现在测试覆盖不到的长尾机型上。比如某款手机的系统在后台对推送通道有特殊优化导致厂商通道连接被延迟又比如某款手机的通知设置里有个通知分类管理默认把App的通知静音。这些极度细碎的问题在真机测试时很难全部覆盖。我的建议是测试用例里至少要覆盖三类设备iOS设备一台、搭载最新Android系统的主流大厂机一台、一台国产老机型低版本系统。同时安排一轮清后台测试和重启手机测试确认App进程被清理、手机重启之后推送是否还能正常收到。这些场景是线上故障高发区。6.5 服务端推送返回成功但客户端没收到这类问题通常是推送服务商已经把消息下发给了厂商通道但厂商通道因为设备不在线、消息过期、通道被限流等原因没有送达。第三方服务商后台通常会有厂商回执数据能看到厂商通道最终是否接收了消息以及错误码。如果没有回执数据可以直接找厂商技术支持查。还有一个容易忽略的点推送消息的厂商类别是否与设备匹配。比如设备是一台小米手机但推送时由于registrationId被错误解析消息发到了华为通道结果直接被丢弃。这类问题在Android多渠道环境下不算罕见究其原因还是设备标识管理混乱。7. 我的一点实用建议和踩坑心得做了这么多推送相关的项目最大的体会是推送不是一个集成完就结束的模块它是一个持续运营、持续优化的系统。技术上它涉及客户端、服务端、厂商通道、第三方服务商多段协作产品上它涉及文案、频控、用户分群、数据监测。任何一个环节掉链子最终用户感知的都是这App总给我瞎发通知或者这App通知总收不到两种评价都会让产品受损。有一个小建议值得单独提出来所有推送消息无论是营销类还是服务类都建议做用户可控制设置。比如在App内增加一个消息通知设置中心让用户自己选择接收哪些类型的推送。表面上看似多了一步操作实际上反而会提高用户对推送的信任度整体授权率和点击率都会更好。这是我自己做一个运动App时验证过的经验开放消息偏好设置后通知权限的整体开启率比之前提高了将近20%。最后再分享一个排查技巧线上推送出问题时先别急着动代码。登录推送服务商后台查一下目标消息的单条明细基本能定位到是服务端没发出去、服务商没转发还是厂商通道拒收。很多团队花半天查代码最后发现只是测试环境下推送服务商的白名单域名没有配置完整。这类问题看起来低级但确实是实战中最高频的。希望这篇内容能帮你少踩几个坑。
返回列表