Android实现推送方式解决方案 - 长链接+心跳机制(MQTT协议)

本文介绍在Android中实现推送方式的基础知识及相关解决方案。推送功能在手机开发中应用的场景是越来起来了,不说别的,就咱们手机上的新闻客户端就时不j时的推送过来新的消息,很方便的阅读最新的新闻信息。这种推送功能是好的一面,可是也会常常看到不少推送过来的垃圾信息,这就让咱们感到厌烦了,关于这个咱们就不能多说什么了,毕竟不少商家要作广告。本文就是来探讨下Android中实现推送功能的一些解决方案,也但愿可以起到抛砖引玉的做用。^_^php

 

  1.推送方式基础知识: html

  在移动互联网时代之前的手机,若是有事情发生须要通知用户,则会有一个窗口弹出,将告诉用户正在发生什么事情。多是未接电话的提示,日历的提醒,或是一封新的彩信。推送功能最先是被用于Email中,用来提示咱们新的信息。因为时代的发展和移动互联网的热潮,推送功能更加地普及,已经再也不仅仅用在推送邮件了,更多地用在咱们的APP中了。java

 

  当咱们开发须要和服务器交互的应用程序时,基本上都须要获取服务器端的数据,好比《地震应急通》就须要及时获取服务器上最新的地震信息。要获取服务器上不定时更新的信息,通常来讲有两种方法:第一种是客户端使用Pull(拉)的方式,就是隔一段时间就去服务器上获取一下信息,看是否有更新的信息出现。第二种就是 服务器使用Push(推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。这样,客户端就能自动的接收到消息。 android

 

  虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,可是明显来讲Push方式比Pull方式更优越。由于Pull方式更费客户端的网络流量,更主要的是费电量,还须要咱们的程序不停地去监测服务端的变化。  git

 

  在开发Android和iPhone应用程序时,咱们每每须要从服务器不定的向手机客户端即时推送各类通知消息。咱们只须要在Android或IPhone的通知栏处向下一拉,就展开了Notification Panel,能够集中一览各类各样通知消息。目前IOS平台上已经有了比较简单的和完美的推送通知解决方案,我会在之后详细介绍IPhone中的解决方案,但是Android平台上实现起来却相对比较麻烦。github

  最近利用几天的时间对Android的推送通知服务进行初步的研究,也但愿能和你们共同探讨一下。spring

 

  2. 几种常见的解决方案实现原理:api

  1)轮询(Pull)方式:应用程序应当阶段性的与服务器进行链接并查询是否有新的消息到达,你必须本身实现与服务器之间的通讯,例如消息排队等。并且你还要考虑轮询的频率,若是太慢可能致使某些消息的延迟,若是太快,则会大量消耗网络带宽和电池。服务器

 

  2)SMS(Push)方式:在Android平台上,你能够经过拦截SMS消息而且解析消息内容来了解服务器的意图,并获取其显示内容进行处理。这是一个不错的想法,我就见过采用这个方案的应用程序。这个方案的好处是,能够实现彻底的实时操做。可是问题是这个方案的成本相对比较高,咱们须要向移动公司缴纳相应的费用。咱们目前很难找到免费的短消息发送网关来实现这种方案。微信

 

  3)持久链接(Push)方式:这个方案能够解决由轮询带来的性能问题,可是仍是会消耗手机的电池。IOS平台的推送服务之因此工做的很好,是由于每一台手机仅仅保持一个与服务器之间的链接,事实上C2DM也是这么工做的。不过刚才也讲了,这个方案存在着不少的不足之处,就是咱们很难在手机上实现一个可靠的服务,目前也没法与IOS平台的推送功能相比。

 

  Android操做系统容许在低内存状况下杀死系统服务,因此咱们的推送通知服务颇有可能就被操做系统Kill掉了。 轮询(Pull)方式和SMS(Push)方式这两个方案也存在明显的不足。至于持久链接(Push)方案也有不足,不过咱们能够经过良好的设计来弥补,以便于让该方案能够有效的工做。毕竟,咱们要知道GMail,GTalk以及GoogleVoice均可以实现实时更新的。

  

  3.第一种解决方案:C2DM云端推送功能。

  在Android手机平台上,Google提供了C2DM(Cloudto Device Messaging)服务,起初我就是准备采用这个服务来实现本身手机上的推送功能,并将其带入本身的项目中。 

 

  Android Cloud to Device Messaging (C2DM)是一个用来帮助开发者从服务器向Android应用程序发送数据的服务。该服务提供了一个简单的、轻量级的机制,容许服务器能够通知移动应用程序直接与服务器进行通讯,以便于从服务器获取应用程序更新和用户数据。C2DM服务负责处理诸如消息排队等事务并向运行于目标设备上的应用程序分发这些消息。关于C2DM具体使用过程,你们能够去查阅相关的资料,在这里先让咱们了解下大体方案状况。

 

  下面是C2DM操做过程示例图:

   

 

  可是通过一番研究发现,这个服务存在很大的问题:  

  1)C2DM内置于Android的2.2系统上,没法兼容老的1.6到2.1系统;

 

  2)C2DM须要依赖于Google官方提供的C2DM服务器,因为国内的网络环境,这个服务常常不可用,若是想要很好的使用,咱们的App Server必须也在国外,这个恐怕不是每一个开发者都可以实现的;

 

  3) 不像在iPhone中,他们把硬件系统集成在一块了。因此对于咱们开发者来讲,若是要在咱们的应用程序中使用C2DM的推送功能,由于对于不一样的这种硬件厂商平台,好比摩托罗拉、华为、中兴作一个手机,他们可能会把Google的这种服务去掉,尤为像在国内就不少这种,把Google这种原生的服务去掉。买了一些像什么山寨机或者是华为这种国产机,可能Google的服务就没有了。而像在国外出的那些可能会内置。

 

  有了上述几个方面的制约,致使我最终放弃了这个方案,不过我想利用另一篇文章来详细的介绍C2DM的框架以及客户端和App Server的相应设置方法,能够做为学习资源让咱们有个参考的资料。 即然C2DM没法知足咱们的要求,那么咱们就须要本身来实现Android手机客户端与App Server之间的通讯协议,保证在App Server想向指定的Android设备发送消息时,Android设备可以及时的收到。

 

  4. 第二种解决方案:MQTT协议实现Android推送功能。

  采用MQTT协议实现Android推送功能也是一种解决方案。MQTT是一个轻量级的消息发布/订阅协议,它是实现基于手机客户端的消息推送服务器的理想解决方案。

  wmqtt.jar 是IBM提供的MQTT协议的实现。咱们能够从这里https://github.com/tokudu/AndroidPushNotificationsDemo)下载该项目的实例代码,而且能够找到一个采用PHP书写的服务器端实现https://github.com/tokudu/PhpMQTTClient)。

 

  架构以下图所示:

      

 

  wmqtt.jar 是IBM提供的MQTT协议的实现。咱们能够从以下站点下载http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg24006006)它。咱们能够将该jar包加入本身的Android应用程序中。

 

  5.第三种解决方案:RSMB实现推送功能。

  Really Small Message Broker (RSMB) ,他是一个简单的MQTT代理,一样由IBM提供,其查看地址是:http://www.alphaworks.ibm.com/tech/rsmb。缺省打开1883端口,应用程序当中,它负责接收来自服务器的消息并将其转发给指定的移动设备。

 

  SAM是一个针对MQTT写的PHP库。咱们能够从这个http://pecl.php.net/package/sam/download/0.2.0地址下载它.

  send_mqtt.php是一个经过POST接收消息而且经过SAM将消息发送给RSMB的PHP脚本。 

 

  6. 第四种解决方案:XMPP协议实现Android推送功能。

  这是我但愿在项目中采用的方案,由于目前它是开源的,对于其简单的推送功能它仍是可以实现的。咱们能够修改其源代码来适应咱们的应用程序。

  事实上Google官方的C2DM服务器底层也是采用XMPP协议进行的封装。XMPP(可扩展通信和表示协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线探测。这个协议可能最终容许因特网用户向因特网上的其余任何人发送即时消息。关于XMPP协议我在上篇博文中已经介绍,你们能够参考下文章:http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378956.html

 

  androidpn是一个基于XMPP协议的java开源Android push notification实现,我会在之后的博文中详细介绍androidpn。它包含了完整的客户端和服务器端。通过源代码研究我发现,该服务器端基本是在另一个开源工程openfire基础上修改实现的,不过比较郁闷的是androidpn的文档是由韩语写的,因此整个研究过程基本都是读源码。

 

  这是androidpn的项目主页:http://sourceforge.net/projects/androidpn/

 

  androidpn实现意图以下图所示:

  

 

  androidpn 客户端须要用到一个基于java的开源XMPP协议包asmack,这个包一样也是基于openfire下的另一个开源项目smack,不过咱们不须要本身编译,能够直接把androidpn客户端里面的asmack.jar拿来使用。客户端利用asmack中提供的XMPPConnection类与服 务器创建持久链接,并经过该链接进行用户注册和登陆认证,一样也是经过这条链接,接收服务器发送的通知。

 

  androidpn服务器端也是java语言实现的,基于openfire开源工程,不过它的Web部分采用的是spring框架,这一点与 openfire是不一样的。Androidpn服务器包含两个部分,一个是侦听在5222端口上的XMPP服务,负责与客户端的 XMPPConnection类进行通讯,做用是用户注册和身份认证,并发送推送通知消息。另一部分是Web服务器,采用一个轻量级的HTTP服务器, 负责接收用户的Web请求。服务器架构以下:

 

 

 

  最上层包含四个组成部分,分别是SessionManager,Auth Manager,PresenceManager以及Notification Manager。SessionManager负责管理客户端与服务器之间的会话,Auth Manager负责客户端用户认证管理,Presence Manager负责管理客户端用户的登陆状态,NotificationManager负责实现服务器向客户端推送消息功能。

 

  这个解决方案的最大优点就是简单,咱们不须要象C2DM那样依赖操做系统版本,也不会担忧某一天Google服务器不可用。利用XMPP协议咱们还能够进一步的对协议进行扩展,实现更为完善的功能。 采用这个方案,咱们目前只能发送文字消息,不过对于推送来讲通常足够了,由于咱们不能期望经过推送获得全部的数据,通常状况下,利用推送只是告诉手机端服务器发生了某些改变,当客户端收到通知之后,应该主动到服务器获取最新的数据,这样才是推送服务的完整实现。 XMPP协议书相对来讲仍是比较简单的,值得咱们进一步研究。

 

  可是在通过一段时间的测试,我发现关于androidpn也存在一些不足之处:

  1. 好比时间过长时,就再也收不到推送的信息了。

  2. 性能上也不够稳定。

    3. 若是将消息从服务器上推送出去,就再也不管理了,无论消息是否成功到达客户端手机上。

 

  等等,总之,androidpn也有不少的缺点。若是咱们要使用androidpn,则还须要作大量的工做。

  至于详细使用过程,咱们会在下个博文中再给你们介绍。

 

  7.第五种解决方案:使用第三方平台。

  第三方平台有商用的也有免费的,咱们能够根据实现状况使用。关于国内的第三方平台,我感受目前比较不错的就是极光推送。关于极光推送目前是免费的,咱们能够直接使用。关于详细状况,你们能够查看它的主页:http://www.jpush.cn/index.jsp,这里再也不详细描述。

  

  关于国外的第三方平台我也见过几个:http://www.push-notification.org/。有兴趣的朋友能够查阅相关信息。使用第三方平台就须要使用别人的服务器,关于这点,你懂的。

 

  8.第六种解决方案:本身搭建一个推送平台。

  这不是一件轻松的工做,固然能够根据各自的须要采起合适的方案。

 

  好了,以上是关于在Android中实现推送方式的基础知识及相关解决方案。

参考:

 

http://www.infoq.com/cn/articles/baidu-android-cloud-push

http://www.cnblogs.com/hanyonglu/archive/2012/03/04/2378971.html

 

1、推送服务简介

 

消息推送,顾名思义,是由一方主动发起,而另外一方与发起方以某一种方式创建链接并接收消息。在Android开发中,这里的发起方咱们把它叫作推送服务器(Push Server),接收方叫作客户端(Client)。相比经过轮询来获取新消息或通知,推送不管是在对客户端的资源消耗仍是设备耗电量来讲都比轮询要好,因此,目前绝大多数须要及时消息推送的App都采用Push的方式来进行消息通知。

push

身在天朝,置身墙内!Android生态系统本来提供了相似于Apple iOS推送服务APNSGCM(Google Cloud Messaging for Android),之前叫C2DM,可是因为某些缘由,致使这项服务在国内不是很好使,为了弥补这个不足,而且我朝各大同胞又想使用Android推送服务,因此国内各大平台陆续推出了GCM的替代品,今天要介绍的就是其中一家,由百度提供的云推送。另外,国内作消息推送服务的还有极光推送和个推等,他们的客户包括新浪微博、淘宝等国内一线大公司。

推送的实现技术简单来讲就是利用Socket维持Client和Server间的一个TCP长链接,经过这种方式能大大下降由轮询方式带来的Device的耗电量和数据访问流量。目前,百度云推送提供的推送服务支持的单一消息体大小是4k,若是超过4k,则建议在消息内携带服务请求URL进行二次请求。目前,百度云推送针对Android端提供通知推送,文本消息推送以及富媒体推送。

2、使用场景

1. 单播消息推送

Push Server向指定的设备(Device)或是用户(User)推送消息,一个用户对应一个userID,一个User可能拥有多台Device,咱们但愿向同一个userID推送消息时,他全部绑定了userID的Device都能收到消息。百度云推送给出的解决方案是经过Client向Push Server注册,并在Client端的监听端口取得Push Server返回的 channelIDuserIDchannelID指定一个终端,在向Push Server注册的过程当中,Device能够发送IMIE码或者UUID做为惟一标示,在Push Server注册后再返回给Client生成的channelIDuserID。这两个ID获取到后由开发者自行维护,注册完毕后,Push Server维护一个注册设备列表,这个列表维护了userIDchannelID以及与Device对应的关系,当须要向指定的设备或用户推送消息时,Push Server会首先遍历这个设备列表,经过这两个ID来作惟一性判断并找到须要推送消息的Device,而后就能够进行消息推送了。

push

实例:用户A发表问题时,记录问题id及其对应的A的userID(或channelID),用户B发表问题回答时,经过服务端API向问题id对应的userID(或channelID)指向的Device推送答案。

2. 分组消息推送

百度云推送经过对Client设置标签(Tag)的方式来进行用户分组,Tag的产生方式能够是由Client维护也能够由Server收集,Push Server针对不一样的Tag进行推送过滤,最终将消息推送到指定的Client。不管是由Client主动设置的Tag仍是由Server根据用户使用习惯收集的,都由Push Server进行统一管理,在基于Tag的分组消息推送实现上,Push Server首先根据指定Tag从全部Tag下遍历出的对应的已注册的Device,从而能够得到与Device对应的userIDchannelID,继而能够针对指定Tag进行分组消息推送。对比单播消息推送,分组消息推送在推送周期上势必要长一些,而且在待推消息列表的维护上也须要作一些处理,哪些消息是推送成功的,哪些是失败的,这须要接收消息推送的Client在接收到消息后给Push Server一个消息回执,这样就保证了消息送达的准确性,若是消息推送失败,则分组列表里的待推消息会继续推送,直到推送消息成功。另外,在消息推送的实时性上,分组消息推送对比单播消息推送会根据分组消息队列的前后存在一个消息接收的延时,比如如今微信公众帐号的推送,就是一个分组消息推送的实例,在消息接收的时效性上对比单播推送存在必定的延时性。

另外,还有一类消息推送使用场景,就是广播消息,该类型能够理解为分组消息的一个特列,即向全部的Tag对应的Client推送消息。广播消息是对全体集合的一个消息推送,在消息队列维护和消息推送时效性上比单个或几个Tag的分组推送成本要高。

实例:给应用提供喜爱设置页面,用户勾选不一样的类别,触发对应Tag的设置,这种方式是由Client主动维护Tag。或者用户阅读了某个类别的图书,触发对应Tag的设置,在服务端,给指定类别的图书设置Tag,后续会根据服务端收集的Tag给应用推送该Tag下的新书信息,这种方式就是由服务端来维护Tag分组。

3、百度云推送Android_SDK

百度提供了完整的Demo帮助开发者集成云推送服务,推送服务SDK经过.jar包和.so文件的方式能够集成到咱们本身的工程中。在此以前,须要到百度开发者中心进行应用注册并获取API Key,这个做为使用推送服务应用的惟一标示,具体流程我就不赘述了,须要使用的话能够直接访问百度开发者中心进行查看。

下面主要看看Android_SDK的总体概览和内部运行机制:

structure

上图是百度云推送Android_SDK的框架图,经过SDK能够绕过复杂的Push HTTP/HTTPS API直接和Push服务器进行交互,主要提供以下功能:

  • Push服务初始化以及Client注册绑定
  • 建立或删除标签(Tag)
  • 接收Push Server的通知并提供自定义展示消息方式
  • 推送统计分析功能,包括通知的点击和删除统计以及应用使用状况统计
  • 富媒体推送

在Android端,总共实现了三个Receiver和一个Service,其中,一个Receiver是用来处理注册绑定后接收服务端返回的channelID等信息:

 
<receiver android:name="com.baidu.android.pushservice.RegistrationReceiver" android:process=": bdservice_v1"<intent-filter> <action android:name="com.baidu.android.pushservice.action.METHOD " /> <action android:name="com.baidu.android.pushservice.action.BIND_SYNC " /> </intent-filter> <intent-filter> <action android:name="android.intent.action.PACKAGE_REMOVED"/> <data android:scheme="package" /> </intent-filter> </receiver>

第二个Receiver是用于接收系统消息以保证PushService正常运行:

</pre></td><td class="code" style="margin:0px; padding:0px; border:0px; font-family:inherit; font-style:inherit; line-height:inherit; font-size:18px; vertical-align:middle; width:1279px"><pre style="white-space:pre-wrap; word-wrap:break-word"><code class="xml" style="margin:0px; padding:0.8em; border:0px; font-style:inherit; line-height:1.45em; vertical-align:baseline; overflow-y:hidden; display:block; overflow-x:auto;  font-family:Menlo,Monaco,'Andale Mono','lucida console','Courier New',monospace!important"><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><receiver</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:name=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">"com.baidu.android.pushservice.PushServiceReceiver"</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:process=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">": bdservice_v1"</span><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important">></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><intent-filter></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><action</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:name=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">"android.intent.action.BOOT_COMPLETED"</span> <span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important">/></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><action</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:name=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">"android.net.conn.CONNECTIVITY_CHANGE"</span> <span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important">/></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><action</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:name=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">"com.baidu.android.pushservice.action.notification.SHOW"</span> <span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important">/></span> <span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"><action</span> <span class="na" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(38,139,210)!important">android:name=</span><span class="s" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; color:rgb(42,161,152)!important">"com.baidu.android.pushservice.action.media.CLICK"</span> <span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important">/></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"></intent-filter></span>
</span><span class="line" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline"><span class="nt" style="margin:0px; padding:0px; border:0px; font-family:inherit; line-height:inherit; vertical-align:baseline; font-weight:bold!important; color:rgb(38,139,210)!important"></receiver></span>
</span></code>

第三个Receiver就是开发者本身实现的用来接收并处理推送消息:

 
<receiver android:name="your.package.PushMessageReceiver"<intent-filter> <!-- 接收 push 消息 --> <action android:name="com.baidu.android.pushservice.action.MESSAGE" /> <!-- 接收 bind、setTags 等 method 的返回结果 --> <action android:name="com.baidu.android.pushservice.action.RECEIVE" /> </intent-filter> </receiver>

一个Service就是在后台运行的用于保障与Push Server维持长链接并作相关处理的后台服务:

 
<service android:name="com.baidu.android.pushservice.PushService" android:exported="true"android:process=" bdservice_v1"/> <!-- push service end -->

在开发者本身须要处理的广播接收器中,能够对接收到的推送消息进行处理,Push消息经过 action为com.baidu.android.pushservice.action.MESSAGE的Intent把数据发送给客户端your.package.PushMessageReceiver,消息格式由应用本身决定,PushService只负责把服务器下发的消息以字符串格式透传给客户端。接口调用回调经过action为com.baidu.android.pushservice.action.RECEIVE的Intent 返回给your.package.PushMessageReceiver。

PushMessageReceiver.java

 
/** * Push消息处理receiver * @Author Ryan * @Create 2013-8-6 下午5:59:38 */ public class PushMessageReceiver extends BroadcastReceiver public static final String TAG PushMessageReceiver.class.getSimpleName(); @Override public void onReceive(final Context contextIntent intentif (intent.getAction().equals(PushConstants.ACTION_MESSAGE)) //获取消息内容 String message intent.getExtras().getString(PushConstants.EXTRA_PUSH_MESSAGE_STRING); //消息的用户自定义内容读取方式 Log.i(TAG"onMessage: " message); else if (intent.getAction().equals(PushConstants.ACTION_RECEIVE)) {//处理绑定等方法的返回数据 //PushManager.startWork()的返回值经过PushConstants.METHOD_BIND获得//获取方法 final String method intent .getStringExtra(PushConstants.EXTRA_METHOD); //方法返回错误码。若绑定返回错误(非0),则应用将不能正常接收消息。 //绑定失败的缘由有多种,如网络缘由,或access token过时。 //请不要在出错时进行简单的startWork调用,这有可能致使死循环。 //能够经过限制重试次数,或者在其余时机从新调用来解决。 final int errorCode intent.getIntExtra(PushConstants.EXTRA_ERROR_CODEPushConstants.ERROR_SUCCESS); //返回内容 final String content new Stringintent.getByteArrayExtra(PushConstants.EXTRA_CONTENT)); //用户在此自定义处理消息,如下代码为demo界面展现用 Log.d(TAG"onMessage: method : " method); Log.d(TAG"onMessage: result : " errorCode); Log.d(TAG"onMessage: content : " content); }

经过在入口Activity的onCreate方法中进行推送服务的注册绑定后,便可在推送管理后台或是本身的应用服务器上进行消息推送的操做了。

 
PushManager.startWork(getApplicationContext(),PushConstants.LOGIN_TYPE_API_KEY"you_api_key");

另外,云推送提供php、java等Server端的SDK供开发者在本身的服务器上实现推送服务进行定制化管理和操做。

4、单服务单通道机制

百度云推送实现了单服务单通道的机制,若是在一台Device上安装了多款Push SDK的应用,不会为每一个应用都建立PushService,而是会采用多应用共享一个PushService的模式。这样既能减小资源消耗也能下降网络流量。PushService运行于一个独立进程,没有和主进程运行于同一进程,因此主进程不须要常驻内存,当有新的Push消息时,PushService会经过Intent发送消息给主进程进行处理。经过Intent,以指定目标应用包名的方式,发送私有消息给应用。应用即不能接收不属于本身的消息,也不能截取别人的消息,同时又下降了消耗,以下为示意图:

structure

后记:现在,国内提供Android推送服务的还有不少家,例如个推和极光推送等,实现的原理大同小异,开发者能够根据自身须要进行选择。身在天朝,置身墙内,用不到GCM,就创造Android Push Service for China自给,或者,出走!

相关文章
相关标签/搜索