@946898963
2018-05-31T17:07:50.000000Z
字数 5120
阅读 1372
Android学习笔记
推送通知是一种技术。
简单点就是客户端获取资源的一种手段。
普通情况下,都是客户端主动的pull。
推送则是服务器端主动push。
客户端不断的查询服务器,检索新内容,也就是所谓的pull 或者轮询方式(具体的实现就是:开定时器(比较AlarmManager和JobScheduler),然后过一段时间就启动一个Service去查询)
客户端和服务器之间维持一个TCP/IP长连接,服务器向客户端push
服务器又新内容时,发送一条类似短信的信令给客户端,客户端收到后从服务器中下载新内容,也就是SMS的推送方式
苹果的推送系统和googleC2DM推送系统其实都是在系统级别维护一个TCP/IP长连接,都是基于第二种的方式进行推送的。第三种方式由于运营商没有免费开放这种信令导致了这种推送在成本上是无法接受的,虽然这种推送的方式非常的稳定,高效和及时。
如果想了解android中各种推送方式请参考这个链接:Android实现推送方式解决方案 这篇博客已经介绍的非常好了。如果想深入了解的话,建议学习:见证Android消息推送时刻。
这里本文重点介绍实现推送的第二种方式。
关于长连接,建议阅读: HTTP的长连接。
客户端跟服务器端维持一个长连接,当有数据到来的时候服务器通过这个长连接主动推送消息到客户端。长连接是通过客户端给服务器端发送心跳包来维持的。在安卓平台的实现推送如果不使用GCM的话(绝大多数都没有使用),剩下的实现推送的方式基本上是大同小异的,就是在应用启动的时候,开启一个服务,该服务独立于应用,即该服务在一个单独的进程里,在该服务启动的时候建立一个跟服务器的连接,此后发送心跳包来维持该连接,当在服务里接收到推送的数据后,可以通过广播或者进程间通信的方式将接收到的数据传递给客户端。
Broadcast
让你的remote service不断的向外发送广播,缺点就是广播是低效且不稳定,易受系统监控影响,有可能丢失某一些时刻的广播数据,不过简单,容易实现,对数据不严格要求可以考虑使用这个方式。IPC
即AIDL方式,如果你对AIDL熟悉,强烈建议你使用这个来实现与remote service的通信,要是不熟悉,会有一定难度,属于Android高阶知识。
应用上述方式进行推送的流程,A向B发送消息,A先将消息发送到自己的服务器,自己的服务器再将数据推送到B。
上面提到实现心跳的Service单独开启一个进程,自我理解,之所以单独开启一个进程,是因为Android上为每一个进程分配的资源都是有限的,单独开一个进程,这个Service就可以独享这个进程的资源,这样这个进程就不容被回收。同时也减少了对主进程中资源的占用。
这里补充下GCM,GCM是安卓2.2以后推出的安卓上的推送机制,使用GCM,第三方应用程序可以搭建自己的服务器,配合Google的GCM Server实现消息的即时通知。使用GCM的推送流程是这样的,如果A向B发送消息,A先将消息发送到自己的服务器,自己的服务器将数据发送到谷歌的服务器,然后谷歌的服务器再将数据推送到B。GCM其实使用的也是TCP/IP长连接,所不同的是它接收推送消息的Google service 是运行在系统级别,从而避免了被操作系统杀死使整个Push机制失效状况的发生(第三方应用程序按照上述的方案实现Push机制,一旦系统内存较低,服务被杀死,那么整个Push机制就失效了),还有一个好处就是所有接收推送消息的应用只使用一个service,维持一个长连接,从而节省了很多电力开销。既然GCM这么好,为什么绝大多数推送都没有使用GCM呢,这是因为GCM要求设备必须是安卓2.2以上,同时手机必须安装了google service,但是国产手机基本都没有装google service,此外由于谷歌的服务器在国外,由于伟大的天朝的墙的原因,谷歌服务器的连接经常会出现问题,这些都限制了GCM的使用。
关于GCM的使用,建议阅读:google的GCM推送使用简介。
顺带补充下Google Service, 手机上的谷歌服务大体上是谷歌产品的公共服务平台,比如谷歌地球、谷歌地图、谷歌导航、谷歌邮箱、谷歌游戏、谷歌GPS轨迹纪录等等软件,都要在安装谷歌服务框架的基础上运行,否则便没法使用或功能受限。因此,如果需要使用谷歌产品的话,就不能删除它。如果确实用不着谷歌产品,能否删除也分两种情况,有的跟操作系统完全做到一起的,那根本就没法删除,除非不用他的刷机包。有的是相对分离的,则可以通过手机的程序管理功能删除掉。
首先我们必须知道,所有的推送功能必须有一个客户端和服务器的长连接,因为推送是由服务器主动向客户端发送消息,如果客户端和服务器之间不存在一个长连接那么服务器是无法来主动连接客户端的。因而推送功能都是基于长连接的基础是上的。IOS长连接是由系统来维护的,也就是说苹果的IOS系统在系统级别维护了一个客户端和苹果服务器的长链接,IOS上的所有应用上的推送都是先将消息推送到苹果的服务器然后将苹果服务器通过这个系统级别的长链接推送到手机终端上,这样的的几个好处为:1.在手机终端始终只要维护一个长连接即可,而且由于这个长链接是系统级别的不会出现被杀死而无法推送的情况。2.省电,不会出现每个应用都各自维护一个自己的长连接。3.安全,只有在苹果注册的开发者才能够进行推送,等等。
android的长连接是由每个应用各自维护的,但是google也推出了和苹果技术架构相似的推送框架,C2DM,云端推送功能,但是由于google的服务器不在中国境内,其他的原因你懂的。所以导致这个推送无法使用,android的开发者不得不自己去维护一个长链接,于是每个应用如果都24小时在线,那么都得各自维护一个长连接,这种电量和流量的消耗是可想而知的。虽然国内也出现了各种推送平台,但是都无法达到只维护一个长连接这种消耗的级别。
android长连接心跳机制
google的GCM推送使用简介
Android推送从服务器到客户端一体化解决方案(1)-socket长连接实现
Android推送从服务器到客户端一体化解决方案(2)-XMPP协议下的Androidpn
开发中的问题:
推送——Android程序员‘一生的痛’!!
一般重连机制都有几个重要参数:心跳时间间隔、重连超时时间及重连次数。其中心跳包每天会将手机从空闲模式唤醒近300次,一般的Android手机每天有超过15-20%的电量被消耗在发送过度频繁的心跳上。另外如果手机连不上服务器而不断的重试,在几小时内就会耗光电池。所以心跳时间不宜过短,据测试微信心跳时间为300s,可以作为一个参考。同样也不能永无休止的重连,重连几次还连不上,可以直接把问题抛给用户,由用户决定是否继续重连
客户端发送心跳包,等待服务端返回响应,若是服务器过了一定时间没有响应,客户端认为连接断开,断开现有的连接,重新建立一个新的连接。
避免心跳服务被回收,即使得心跳服务常驻内存,这就涉及到进程保活,关于进程保活,建议阅读:Android进程保活。
针对特定平台用特定的推送,比如如果你的应用在小米手机的用户量比较多,那你可以用小米的推送服务,因为MIU系统不会回收小米推送的服务的,自己的东西嘛。
说说保持一个长连接很简单,为什么长连接会带来很多麻烦,还提示从耗电量,微信分析
当一台智能手机连上移动网络时,其实并没有真正连接上Internet,运营商分配给手机的IP其实是运营商的内网IP,手机终端要连接上Internet还必须通过运营商的网关进行IP地址的转换,这个网关简称为NAT(NetWork Address Translation),简单来说就是手机终端连接Internet其实就是移动内网IP,端口,外网IP之间相互映射。相当于在手机终端在移动无线网络这堵墙上打个洞与外面的Internet相连。由于大部分的移动无线网络运营商为了减少网关NAT映射表的负荷,如果一个链路有一段时间没有通信时就会删除其对应表,造成链路中断,正是这种刻意缩短空闲连接的释放超时,原本是想节省信道资源的作用,没想到让互联网的应用不得以远高于正常频率发送心跳来维护推送的长连接。这也是为什么会有之前的信令风暴,微信摇收费的传言,因为这类的应用发送心跳的频率是很短的,既造成了信道资源的浪费,也造成了手机电量的快速消耗。
android长连接心跳机制
微信收费事件背后被广泛忽略的技术细节——长连接心跳周期
微信的大规模使用真的会过多占用信令,影响通讯稳定吗? - 知乎
互联网推送服务原理:长连接+心跳机制(MQTT协议)
从通信的角度分析一下微信推送的长连接的弊端——网易面试题
微信是一直保持的和服务器tcp连接吗?
试试把APP心跳的前因后果解释更简单明白?
补充内容:
信令,是通讯设备之间任何实际应用信息的传送总是伴随着一些控制信息的传递,它们按照既定的通讯协议工作,将应用信息安全、可靠、高效地传送到目的地。这些信息在计算机网络中叫做协议控制信息,而在电信网中叫做信令(Signal)。信令是信息的传递,不是占用的问题啊。当然不支持微信收费。
总结来说:信令就是一些控制信息,信令风暴就是由于网络中的信令过多导致的网络拥塞。
Service和推送通知,通知有没有可能出现有推送但是通知栏收不到通知?service被kill掉会如何?如何保证service不被kill掉
可能,原因如下
- 负责接收推送消息的service由于内存的原因,被kill掉了。
- 负责接收推送消息的service接收到了推送下来的消息,但是service往外传送这个消息的过程出错,service往外传送这个消息基本两种方式,一种是广播,一种是IPC,可能是广播的信息丢失,或者跨进程通信的过程中出现了问题。
- 由于某些原因长连接断开了。
service被kill掉就会出现接收不到推送的消息的情况
如何保持service不被kill掉,就是使service常驻内存的问题,方法在长连接的优化里讲过了。
What is push notification?
本地推送:程序内部弹出通知到用户设备
远程推送:由推送服务器推送通知到用户设备
如何实现消息推送,有哪些方式,各自优缺点,最常使用哪种?
- 一:客户端不断的查询服务器,检索新内容,也就是所谓的pull 或者轮询方式
- 二:客户端和服务器之间维持一个TCP/IP长连接,服务器向客户端push
- 三:服务器又新内容时,发送一条类似短信的信令给客户端,客户端收到后从服务器中下载新内容,也就是SMS的推送方式
最常用的是Push的方式,相关的知识,见上面的内容
还有许多的面试题目,大家自己动手,丰衣足食了,不过我感觉只要把我上面总结的知识搞懂,应付关于推送的问题,应该是没有多大的问题了。
最后附上一些关于推送的相关链接,方便大家自己学习
博文
HTTP长连接和短连接
Android客户端消息推送原理简介
极光推送博客
推送的原理是什么?
个推技术实现原理介绍
android 如何取得正在运行的service对象
互联网推送服务原理:长连接+心跳机制(MQTT协议)
从通信的角度分析一下微信推送的长连接的弊端——网易面试题
试试把APP心跳的前因后果解释更简单明白?
还有一篇关于优化的
移动网络下的性能优化之省电篇
知乎
服务端是如何主动推送信息到客户端的?
Push mail 的实现原理是什么?
为什么微信不使用GCM服务推送消息?
服务端是如何主动推送信息到客户端的?
关于安卓推送的的选择?最想知道微信是什么样的?
app推送的策略是咋样的?
为什么 Android 的后台推送不如 iOS 的推送使用广泛?
Android的推送sdk是如何唤醒App的?
在以TCP为连接方式的服务器中,为什么在服务端设计当中需要考虑心跳?
怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死?
待补充,如何自己实现心跳包,断线重连