推送和移动互联的关系,已经密不可分。每天你收到的推送是各大app的强有力的吸引用户黏住用户的工具。
那我们来具体了解下推送吧。目前的两大平台ios和安卓的推送的实现是有很大差异的。以下分开描述。
IOS&android简要对比
IOS推送即APNS - Apple Push Notification Service,依托一个或几个系统常驻进程,是全局的(接管所有应用的消息推送)的独立于应用之外,是设备和苹果服务器之间的通讯,而非应用的提供商服务器。
比如,网易云课堂的服务器(Provider)给苹果公司对应的服务器(APNS)发出通知,然后再中转传送到设备(Devices)上。当你接收到通知,打开应用,才开始从云课堂服务器接收数据。
而android的推送是各应用有各自的单独后台进程和各自的服务器通讯,交换数据,来达到推送的目的。比如云课堂有自己单独的推送进程:com.netease.edu.study.enterprise:pushservice。
当该进程被kill掉之后,则无法收到推送。IOS则不存在类似问题。 另外其实 Android 也有类似 APNS 的 GCM(Google Cloud Message),属于开发者可选,非强制。而 Google 不强制的结果就是:没人真正为用户的电池负责。也因为整个技术方案非强制, Android 的 Apps 在接收到推送后的表现更为灵活。
所以iOS 的消息推送机制使得应用本身不能有常驻的后台进程,系统的开销少,内存使用更少,而 Android 则开销更大。
推送的一般技术原理
要理解推送的实现原理,首先要了解device_token。
UDID - iOS Unique Device ID,是每个iphone的标识符,可以通过连接XCode查看到,如下图中的identifier就是该设备的UDID。
![推送怎么玩 - 网易杭州QA - 网易杭州 QA Team](http://img1.ph.126.net/xEHs4OI3JjzdZJqgxrWpFQ==/6632399274280071991.jpg)
Bundle ID(Bundle Identifier):一款iOS应用的唯一标识,应用与Bundle ID之间是唯一对应关系。应用新建成功后,Bundle ID将不可修改,如必须修改只能创建一个新的应用,届时App ID、App Key和App Secret也将重新分配,旧版用户将无法收到针对新Bundle ID的推送。
苹果服务器根据我们这一台设备的UDID和app的bundleID混编而成的deviceToken,我们需要将这个deviceToken传送给我们的服务器端,或者登陆用户的时候作为参数传给服务器.这样一个用户对象就绑定了一个deviceToken.当需要给这个用户推送消息的时候,我们自己的后台服务器,就会找这个用户对应的deviceToken和要发送的推送内容,直接发送到苹果的apns服务器,然后由苹果的apns服务器将消息推送到该deviceToekn对应的手机上。
deviceToken是ios设备在APNS上的标识(苹果服务器根据我们这一台设备的UDID和app的bundleID混编而成的deviceToken)用于推送服务。每个设备上的每个app有两个deviceToken,一个用于开发测试,一个用于生产环境。应用需要每次启动的时候都去注册远程通知,注册成功, APNs 会返回一个设备的标识符即deviceToken 给 App,一个用户对象就绑定了一个deviceToken.当需要给这个用户推送消息的时候,我们自己的后台服务器,就会找这个用户对应的deviceToken和要发送的推送内容,直接发送到苹果的apns服务器,然后由苹果的apns服务器将消息推送到该deviceToekn对应的手机上。
在需要发送push时,我们的服务端就会取出要发送的设备的device token,然后以下图所示的结构,组成字符串,然后将其发送到的APNs
![推送怎么玩 - 网易杭州QA - 网易杭州 QA Team](http://img1.ph.126.net/PDGtZwutTdiI7EpkWASFSg==/6632028738864177988.jpg)
第一个部分是命令标示符,第二个部分是我们的deviceToken的长度,第三部分是我们的deviceToken字符串,第四部分是推送消息体(Payload)的长度,最后一部分也就是真正的消息内容了,里面包含了推送消息的基本信息,比如消息内容,应用Icon右上角显示多少数字以及推送消息到达时所播放的声音等。
整个过程是这样:
首先,设备安装了具有推送功能的应用, iOS设备在有网络的情况下会连接APNs推送服务器,连接过程中,APNS 服务器会验证device_token,连接成功后维持一个基于TCP 的长连接;Provider(我们自己的应用服务器)收到需要被推送的消息并结合被推送的 iOS设备的device_token一起打包发送给APNS服务器;APNS服务器将推送信息推送给指定device_token的iOS设备,iOS设备收到推送消息后通知我们的应用程序并显示和提示用户(声音、弹出框)。
![推送怎么玩 - 网易杭州QA - 网易杭州 QA Team](http://img0.ph.126.net/lOSVRsYefk9VrumDI31KOw==/6632134291980451029.jpg)
安卓推送
GCM
Google Cloud Messaging是 Google 自己的一套推送服务,也是系统级别的,但是众所周知,Google 的服务在国内根本没法使用,只能放弃。
轮询
轮询是最简单的与服务器保持通信的方式,即循环向服务器通信。这个方案的特点就是通信由客户端主动发起,你需要自己实现轮询消息队列、频率等等参数,在功耗和效果间做权衡,类似于TCP的短连接。
SMS
这个其实就是借助短信来实现信息的展示,只不过把短信内容展示到了Notification中,这个方案,到达率确实高,毕竟短信是比较可靠、稳定的,但劣势也很明显,就是成本很高,而且在Android平台上,短信的权限比较开放,容易被劫持。
长连接
长连接和前面提到的短连接,都是基于Socket连接的方式,他们的区别在与,短连接是每次数据传输完毕后就断开连接,而长连接不会。所以,基于轮询的方式,每次都要进行链路的连接,性能消耗更大,基于长连接的方式,就是对这点的改进。应用一旦与服务器连接成功,并不会主动断开连接,后面的通信都基于这个通道。目前大部分的推送服务都是基于长连接的推送,在后台维护一个Service,维持应用与服务端之间的TCP长连接。目前基本上是最多选择的方案。
但是目前基于成本上的考虑,大多数中小型公司都会选择使用第三方推送服务。
第三方推送服务
目前来说做的比较好的推送服务大概有小米推送、腾讯信鸽推送、百度推送、极光推送、友盟推送等。这些推送服务大都有以下特点:
免费
当然部分公司也有收费的,号称更稳定、推送到达率更高,但大部分都还是用的免费版。
服务会被杀死
由于 Android 系统的机制,后台推送 Service 会被各种主动的或是被动的行为给杀死,而服务一旦被杀死,意味着就接收不到推送消息。
多个 app 共用一条推送通道
什么意思呢?就是如果有多个 app 都使用了同一家推送服务,那么这些 app 共用一条消息通道,即使你家的 app 推送服务被杀死了,那么只要用户打开了其他集成该推送服务的 app ,你家的推送就能接受到消息。比如云课堂企业版现在使用的小米推送服务,云课堂企业版被杀死了,但是手机上只要其它也使用小米推送的app的进程还在,云课堂企业版还是能接收到推送消息。
每家的推送服务都号称推送到达率很高,号称自己家的推送服务更不容易被杀死,号称自己的推送更稳定更有保证,然而我要说的是,各家都差不多,技术上你能实现的,别家一样能实现,到达率也都差不多,据我观察平均推送到达率能达到 70% 左右都算不错的了,那么到底该怎么选择呢?
有一点比较特殊的是有些推送服务有自己家品牌的手机,比如小米有自己的手机,而在 MIUI 系统上小米推送是作为系统级的服务,不会被杀死,毕竟一家人,总不至于傻到把自己家的服务给干掉吧?所以这就是一个巨大的优势了。类似的华为推送服务在自己家的手机系统上也不会被杀死。
各大手机厂商都宣传自己家的手机市场份额第一,然而我要说的是如今市场上的 Android 手机只分小米手机跟其他手机,什么意思?就是小米手机是目前市场份额第一,而且远远领先其他手机,这个在我们自己家 app 的数据上看就是这样,而这里有一份友盟发布的 Android 设备活跃的排名数据,地址在这里:http://www.umindex.com
以小米手机的市场份额,加上小米推送在 MIUI 上不被杀死这一大特性,致使选择小米推送是第一选择。目前云课堂企业版安卓也选择了小米推送服务(哈哈)。
所以,你可以选择直接集成某个第三方推送,如果你想要把推送更优化下,那么可以集成多个推送服务,针对不同的渠道用不同的推送,比如小米渠道用小米推送,华为渠道用华为推送,其他渠道用信鸽推送等,但是这种也比较麻烦,具体怎么做看自己利弊权衡。