在开发Android和iPhone应用程序时,我们往往需要从服务器不定的向手机客户端即时推送各种通知消息。
消息通知
解决方法有两种:
1 轮询(Poll)
应用程序应当阶段性的与服务器进行连接并查询是否有新的消息到达,你必须自己实现与服务器之间的通信,例如消息排队等。而且你还要考虑轮询的频率,如果太慢可能导致某些消息的延迟,如果太快,则会大量消耗网络带宽和电池。
然而,每5分钟轮询一次,长期下去,会消耗手机10%的电量。
2 Push
a)短信SMS。在Android平台上,你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图。服务端用特定号码给特定设备发送命令。设备根据收到的命令执行操作。但是问题是这个方案的成本相对比较高,你很难找到免费的短消息发送网关。
b)持久连接(Persistent connection)。这个方案可以解决由轮询带来的性能问题,但是还是会消耗手机的电池。Android操作系统会维持一个长连接,只是维持连接的话,对电量消耗较小,对消耗电量的对比,见:Android C2DM Presentation at O'Reilly AndroidOpen Conference。
Android从2.2版本开始增加了Cloud to Device Messaging(C2DM)框架,在系统中支持了Push功能,基于Android平台使用Push功能更加简单了。虽然C2DM目前还处在实验室阶段,不过小规模的使用应该没问题。
C2DM框架
使用Android的C2DM功能有几个要求:
1. 需要Android2.2及以上的系统版本。
2. 使用C2DM功能的Android设备上需要设置好Google的账户。
3. 需要在这里注册使用C2DM功能的用户邮箱账号(最好为C2DM单独注册一个Gmail邮箱账号)。
我们接下来C2DM的一个完整过程,这里借用一下Google官方推出的Chrome To Phone过程图来说明下。
图1 C2DM操作过程图
要使用C2DM来进行Push操作,基本上要使用以下6个步骤:
(1)注册:Android设备把使用C2DM功能的用户账户(比如android.c2dm.demo@gmail.com)和App名称发送给C2DM服务器。
(2)C2DM服务器会返回一个registration_id值给Android设备,设备需要保存这个registration_id值。
(3)Android设备把获得的registration_id和C2DM功能的用户账户(android.c2dm.demo@gmail.com)发送给自己的服务器,不过一般用户账户信息因为和服务器确定好的,所以不必发送。
这样Android设备就完成了C2DM功能的注册过程,接下来就可以接收C2DM服务器Push过来的消息了。
(4)服务器获得数据。这里图中的例子Chrome To Phone,服务器接收到Chrome浏览器发送的数据。数据也可以是服务器本地产生的。这里的服务器是Google AppEngine(很好的一项服务,可惜在国内被屏了),要换成自己的服务器。服务器还要获取注册使用C2DM功能的用户账户(android.c2dm.demo@gmail.com)的ClientLogin权限Auth。
(5)服务器把要发送的数据和registration_id一起,并且头部带上获取的Auth,使用POST的方式发送给C2DM服务器。
(6)C2DM服务器会以Push的方式把数据发送给对应的Android设备,Android设备只要在程序中按之前和服务器商量好的格式从对应的key中获取数据即可。
对C2DM的分析以及代码示例,可以参见:Android Cloud to Device Messaging (C2DM) - Tutorial
自己实现Push机制
XMPP(可扩展通讯和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测。事实上Google官方的C2DM服务器底层也是采用XMPP协议进行的封装。
如何自己实现,见:Android推送通知指南