# 浅谈iOS和Android后台实时消息推送的原理和区别

> 前言 iOS和Android上的实时消息推送差异很大，往小了说是技术实现的差异，往大了说是系统实现理念的不同。实时消息推送在移动端互联网时代很平常，也很重要，它的存在让智能终端真正成为全时信息传播的工具。本文将从原理上谈谈两个平台上实时消息推送的区别。

* 简要对比

  * iOS 系统的推送（APNS，即 Apple Push Notification Service）依托一个或几个系统常驻进程运作，是全局的（接管所有应用的消息推送），所以可看作是独立于应用之外，而且是设备和苹果服务器之间的通讯，而非应用的提供商服务器。你的例子里面，腾讯 QQ 的服务器（Provider）会给苹果公司对应的服务器（APNs）发出通知，然后再中转传送到你的设备（Devices）之上。当你接收到通知，打开应用，才开始从腾讯服务器接收数据，跟你之前看到通知里内容一样，但却是经由两个不同的通道而来。

  * Android，就不同，更像是传统桌面电脑系统做法。每个需要后台推送的应用有各自的单独后台进程，才能和各自的服务器通讯，交换数据。另外其实 Android 也有类似 APNS 的 GCM（Google Cloud Message），属于开发者可选，非强制。

    * 技术原理

      * 首先讲解下服务器如何先找到设备、再找到app的问题。

        * 每一个设备都有一个自己的设备号，而设备中的app又都有一个唯一的包名。所以服务器只需要找到设备号与包名就可以定位到某个设备的某个应用，而这设备号与包名会一起构成一个标识符，叫做device\_token，因此问题就简化为把device\_token与消息内容等信息交给服务器，服务器把内容发到唯一的device\_token上。这就好像你在上海要通过顺丰寄送一个快件儿给某某小区的某某房间，那么快件儿首先会邮递到顺丰公司在北京的总站点，之后再根据小区的地址投递/路由到某某房间，这样一个寄件过程就算完成了。

      * iOS 实时消息推送

        iOS的推送是通过苹果自己的APNs服务进行的，用户需要将device\_token以及消息内容等推送信息交给APNs服务器，剩下的均由苹果自己来完成。iOS应用的推送大部分情况下都要依赖苹果生态提供的APNs（Apple Push Notification Service）服务。
https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/db29e6a729147172d199cde6e2cf3682_hd.png
        ![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/db29e6a729147172d199cde6e2cf3682_hd.png)

        首先作为设备标识的device-token是由APNs颁发的，App开发者或者第三方推送平台\(图中的Provider\)做的工作是收集这个device-token，APNs的推送是要求基于APNs颁发的device-token来推送的。只有正确的device-token会被APNs接受，如果是一个错误的、或者无效的device-token\(比如App已经卸载了\)，APNs就不会接受。

        ![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/442e4085cf4b8f62c7ad359343c5f155_hd.png)

        接着开发者使用第三方推送平台（图中的Provider）在将推送内容与范围选定之后进行推送，第三方推送平台将信息提交给APNs，剩下的操作全部都由APNs来进行完成，整个过程第三方推送平台就不能控制了。但是如果提供的device\_token是失效的（app被卸载、系统版本升级导致device\_token变化等情况）那么推送过程就会被中断，频繁的断线重连甚至会被APNs认为是一直DoS攻击。（[详情可以参考为什么苹果的推送，两次推送之间间隔比较久的话，第二次推送会很慢？](http://www.baidu.com)）

      * Android  实时消息推送  
        Android平台在不使用GCM的情况下就需要将自己的服务器或是第三方推送服务提供商的服务器与设备建立一条长连接，通过长连接进行推送。但是不建议自己设置服务器实现推送功能，一是因为成本太高（开发成本、维护成本），自己搭建的服务器无论是稳定性还是速度上都比不了第三方推送服务提供商的效果。另一个是因为自己的数据量较小，使用第三方推送服务提供商可以用他们的维度进行推送，实现精准推送。友盟推送就是做的比较好的，可以根据用户分群、地区、语言等多维度进行推送，最大程度减少对于用户的干扰，仅把消息推送给相关用户。![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/224420fhxsp8e00v0s0b0s.png)

      * 开发者通过第三方推送服务提供商将信息直接下发给需要的设备，第三方推送服务提供商与设备建立一条长连接通道，并且将消息路由到APP中（图中的设备1与设备2），对于像设备3这种无网络连接或是没有成功建立长连接通道的设备，会在设备3连网且推送消息没有过期的情况下自动收到由第三方推送服务提供商推送过来的消息，保证消息不会丢失。

  * ## 实现上的差异所带来的直观感受

    * ### iOS的实时消息推送

      iOS 在系统级别有一个推送服务程序使用 5223 端口。使用这个端口的协议源于 Jabber 后来发展为 XMPP ，被用于 Gtalk 等 IM 软件中。

      ![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/224819kyaynn1zzoyoulzn.jpg.png)

      所以 iOS 的推送可以不严谨的理解为：

      * 苹果服务器朝手机后台挂的一个 IM 服务程序发送的消息。
      * 然后，系统根据该 IM 消息识别告诉哪个 Apps 具体发生了什么事

      * 然后，系统分别通知这些 Apps 。

      带来的好处是不会出现杀后台这种脑残事。（不用大量 Apps / Apps 的服务为了推送挂后台）。也不会出现 Apps 被杀就收不到推送这种脑残事（早一点的新浪微博 Android 版仍然如此）。

    * Android的实时消息推送  
      Apps 挂后台一直是 Android 引以为豪的特性（虽然我真的不知道是好处多还是坏处多。。），大家挂后台等待推送就成为技术选择。当然， Google 事后也提供类似苹果的推送方式了。倒也谈不上抄袭，毕竟苹果的整个技术实现也没有什么特别创新之处。

      用户的电池？ Apps 的开发者不会站在系统层面考虑的。他会假设其他 Apps 没有那么“不自觉”。而 Google 不强制的结果就是：没人真正为用户的电池负责。

      但是， Google 的方案也并非全是悲剧：也因为整个技术方案非强制， Android 的 Apps 在接收到推送后的表现更为灵活。像 Line 的 Android 版本可以在推送通知的 Popup 上直接回复， iOS 就需要越狱才能做到了。



