`

[原创]通过代码及流程图说明Google在Android上的Push机制的实现

阅读更多
声明: 如果您要转载, 请事先征得本人的同意后方可并且请您附上原文链接. 本人保留一切权利. 多谢!

Google从FroYo版本后引入了C2DM (Cloud to Device Messaging)框架:
http://code.google.com/android/c2dm/index.html
Android Cloud to Device Messaging (C2DM) is a service that helps developers send data from servers to their applications on Android devices. The service provides a simple, lightweight mechanism that servers can use to tell mobile applications to contact the server directly, to fetch updated application or user data. The C2DM service handles all aspects of queueing of messages and delivery to the target application running on the target device.

这个C2DM框架实际上就是一种Push机制, 当服务器端有changes(creates/updates/deletes)时, 服务器端立刻会通过Push机制通知客户端, 然后客户端会通过Sync机制从服务器端获取server-side diffs, 同时也会把client-side diffs发送给服务器端. 通过Push机制, 用户可以及时获得服务器端的改动, 因此有更好的用户体验.

注:
1. Push机制的实现有多种, 比如通过SMS, 以及现在介绍的C2DM.
2. Android上的Sync机制这里不做过多介绍. 实际上对应下面介绍的内容Google是把Push机制和Sync机制一起使用的.

那么, C2DM的实现原理是什么呢? XMPP!!! 和Android GTalk Client的协议实现一样, 都是XMPP, 并且用的都是同一个XMPP框架, XMPP Stack的实现用的是开源的Smack. 其实, 在FroYo之前, Google的Push机制直接就是在XMPP上面, 只不过在引入了C2DM后, 变成Push机制在C2DM上面, 然后C2DM在XMPP上面了.

下面, 通过介绍Android上Google Contacts/Calendar如何利用C2DM实现Push机制来进行说明. 说的顺序可能比较乱, 大家慢慢理解, 并且其中的code只是用来帮助大家来进行理解.

1. 在AndroidManifest.xml上declare了一个broadcast receiver和一个对应的service用来接收C2DM发送的通知.
<receiver android:name=".subscribedfeeds.SubscribedFeedsBroadcastReceiver">
	<intent-filter>
		<action android:name="com.google.android.c2dm.intent.RECEIVE" />
		<category android:name="com.google.android.gsf.subscribedfeeds" />
	</intent-filter>
</receiver>
<service android:name=".subscribedfeeds.SubscribedFeedsIntentService" />

Google Sync是通过Atom Feed协议进行的. 这样当Server端有changes后, 会通过C2DM框架发送"com.google.android.c2dm.intent.RECEIVE" action给SubscribedFeedsBroadcastReceiver,  而SubscribedFeedsBroadcastReceiver在onReceive()方法启动SubscribedFeedsIntentService. 其可能的代码为:
public class SubscribedFeedsBroadcastReceiver extends BroadcastReceiver {
  public void onReceive(Context context, Intent intent) {
    if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) {
        intent.setClass(context, SubscribedFeedsIntentService.class);
        context.startService(intent);
    }
  }
}


关于"com.google.android.c2dm.intent.RECEIVE" action, 这是C2DM框架定义的标准action, 可以参考C2DM开发文档.


2. C2DM框架什么时候以及如何发送"com.google.android.c2dm.intent.RECEIVE" action.

这里用到的就是XMPP协议扩展. 这里扩展了XMPP的<message> packet, 在其中加入了自定义的elements. 当Google Server有changes后, 会通过XMPP发送<message>给Android上的XMPP client框架,  XMPP client框架会解析<message> packet, 如果发现是关于Google Sync的<message> packet, 则发送"com.google.android.c2dm.intent.RECEIVE" action.
如何接收自定义的XMPP packets呢? 需要首先了解一下Smack的API, 这里不赘述.

2.1 类DataMessageManager
DataMessageManager是一个PacketListener, 当有特定的Packets到达时会调用它的processPacket()方法.
public class DataMessageManager implements PacketListener
{
......
}


2.2 注册DataMessageManager这个PacketListener
PacketTypeFilter filter = new PacketTypeFilter(DataMessage.class);
connection.addPacketListener(this, localPacketTypeFilter);

注意这里的PacketTypeFilter用的是DataMessage, 表示DataMessage这样的XMPP packets才是需要处理的Packets.

2.3 类DataMessage
public class DataMessage extends Message
{
    ......
    private ArrayList<AppData> mAppDataList;
    private String mCategory;
    private boolean mFromTrustedServer = 0;
    private String mPermission;
    private String mToken;
    ......
}

其中override了一个方法:
public String getExtensionsXML() {
    StringBuilder buf = new StringBuilder()
    buf.append("<data").append(" xmlns=\"")append("google:mobile:data").append("\"");
    if (getCategory() != null)
      buf.append(" category=\"").append(getCategory()).append("\"");
    if (getToken() != null)
      buf.append(" token=\"").append(getToken()).append("\"");
    if (getPermission() != null)
      buf.append(" permission=\"").append(getPermission()).append("\"");
    if (this.mFromTrustedServer)
      buf.append(" from-trusted-server=\"true\"");
    buf.append(">");
    int size = getAppDataSize();
    for (int i = 0; i < size; i++) {
        AppData appData = (AppData)this.mAppDataList.get(i);
        buf.append("<app-data key=\"").append(appData.getKey()).append("\" value=\"")
            .append(appData.getValue()).append("\" />");
    }
    
    buf.append("</data>";
    return buf.toString();
}

从这里可以发现, DataMessage对应的是类似下面的XMPP packets:
<message id="zUwxRf4-9" persistent_id="0:1295969265963580%e7a71353002ea1e0" from="google.com" type="headline"><data xmlns="google:mobile:data" category="GSYNC_TICKLE" token="cl_6" from-trusted-server="true"><app-data key="account" value="zhangsan.android@gmail.com" /></data></message>


也就是说, 当Server端有changes需要客户端来sync的时候, 会发送类似与上面的消息给客户端, 这个消息会被DataMessageManager处理.

而在DataMessageManager的processPacket()方法中, 会再做如下判断:
String category= dataMessage.getCategory();
if ("GSYNC_TICKLE".equals(str2))
      category = "com.google.android.gsf.subscribedfeeds";
Intent intent = new Intent("com.google.android.c2dm.intent.RECEIVE");
intent.addCategory(category);
......
context.sendBroadcast(intent);


这个code会认为category为"GSYNC_TICKLE"的XMPP packets才是有关Google Sync的, 并做相应转换.

3. SubscribedFeedsIntentService被启动, 会调用下面的API进行Sync, 后面涉及到的就是Android的Sync机制了, 如果有时间再解释.
ContentResolver.requestSync(......);


大概的时序图为:





  • 大小: 16.1 KB
  • 大小: 3.1 KB
5
5
分享到:
评论
12 楼 langdechuanshuo 2014-07-14  
楼主你用什么工具画出那个图片的,我之前用过一段时间,在华为的时候,但是出来就不记得了。 一直想不起来。能告诉我吗!
11 楼 fajaven 2012-11-03  
C2DM (新的名字叫 GCM)在国内实际上用不了,因为:
1)国内大部分 Android 手机都没有 Google帐号,所以用不了 Google服务
2)国内 Google服务不稳定。

所以,大家一般的选择是:自己用开源项目如 androidpn 搭建整套环境;另一种选择是使用第三方服务。

androidpn开源不成熟,问题还是挺多的。第三方服务方面,目前国内刚出来了一个,叫极光推送 (http://www.jpush.cn),它提供免费的消息推送服务,最快3分钟能够集成跑起来。
10 楼 fajaven 2012-11-03  
JavaLaDeng 写道
这个必须要smack包吧..??


需要 smack 包是标准的开源方式,比如 androidpn

9 楼 bluceshang 2011-10-20  
AdSFJLSDGH
8 楼 bluceshang 2011-10-20  
    
7 楼 JavaLaDeng 2011-10-09  
这个必须要smack包吧..??
6 楼 JavaLaDeng 2011-10-09  
楼主可在,能否给一个demo?包括服务端的 772008232@qq.com 谢谢..
5 楼 dengsh2008 2011-02-25  
我也想知道服务器是如何通知手机的,手机又不是一直在上网。
4 楼 ak121077313 2011-02-22  
我只想知道"这样当Server端有changes后, 会通过C2DM框架发送"com.google.android.c2dm.intent.RECEIVE" action" service 是怎么发送给客户端的
3 楼 laiyangdeli 2011-02-10  
zhs2472 写道
不用一直开着吧,貌似是接到命令才启动的Service

service一直开着还是需要的时候再开着, 都无所谓了,根据需要. Service各种情况都能满足的.
2 楼 zhs2472 2011-02-10  
不用一直开着吧,貌似是接到命令才启动的Service
1 楼 yangrunfei 2011-02-10  
,是不是这个服务客户端一直在开着呢,可以关闭不?

相关推荐

    Android PushMessage百度的-IT计算机-毕业设计.zip

    在Android系统中,通常通过Google的Firebase Cloud Messaging (FCM) 或第三方服务如百度云推送来实现这一功能。 百度云推送作为国内主流的推送服务之一,提供了丰富的API和SDK,支持多种推送场景,包括单播、群播、...

    Android心电云

    在Android平台上,"Android心电云"是一种集成多种功能的技术解决方案,主要涉及到蓝牙通信、数据上传、支付服务以及推送消息的处理。以下是这些关键知识点的详细说明: 1. **Android蓝牙通信**:Android系统提供了...

    手机新生小助手_源代码

    2. **用户界面(UI)设计**:源代码中包含了应用的界面布局和交互设计,这涉及到UI设计原则和响应式布局,以确保在不同尺寸的设备上都能良好显示。 3. **数据管理**:应用可能使用SQLite数据库或者云存储服务来存储...

    Android 基于XMPP协议IM聊天实现(客户端+服务端) 源码

    在本文中,我们将深入探讨如何使用XMPP协议在Android平台上实现一个完整的即时通讯(IM)系统,包括客户端和服务器端的实现。XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的开放标准,广泛用于...

    android 推送

    在移动应用开发过程中,特别是在Android平台上,为了使应用能够实时地获取服务器端的最新信息,开发者通常面临两种选择:Pull(拉取)和Push(推送)。Pull方式意味着客户端定期向服务器请求数据更新,而Push则表示...

    android4.2应用程序源码之Mms

    Android 4.2作为Google推出的Android操作系统的一个版本,其源码开放给开发者,旨在提供一个强大的平台,让开发者能够理解和定制系统功能。对于Mms应用程序源码的研究,是深入理解Android消息服务机制的关键,特别是...

    android 定位+百度推送+引导页轮播+判断第一次进入

    在Android开发中,集成定位、消息推送以及引导页轮播等功能是常见的需求,尤其是在构建一款完整的应用程序时。这里我们主要探讨“android 定位+百度推送+引导页轮播+判断第一次进入”的技术要点。 首先,让我们从...

    Android计算器游戏大作业

    【Android计算器游戏大作业】是一个基于Android平台的项目,旨在帮助学生或开发者深入理解Android应用开发,特别是游戏开发的相关知识。这个项目可能涉及到构建一个功能丰富的计算器应用,并将其设计成游戏的形式,...

    在Android Emulator上安装App Market-g

    在Android Emulator上安装App Market-g这一主题主要涉及的是如何在Android模拟器中安装和使用第三方应用市场,以便获取和安装更多的应用程序。Android Emulator是Android Studio开发工具的一部分,它为开发者提供了...

    android应用源码OssSystem(OA系统图书管理简单版).zip源码资源下载

    开发者需了解Android的运行时权限机制,以适配Android 6.0及以上版本。 8. UI设计与交互 图书管理应用需要友好的用户界面,包括搜索、筛选、排序等功能。开发者需要熟练使用Android的UI控件,如RecyclerView展示...

    安卓Android源码——及时通讯源码:实时对讲机.zip

    在安卓(Android)平台上开发应用程序时,实时通讯(Real-Time Communication, RTC)是常见的需求,尤其是在构建即时通讯应用,如实时对讲机功能时。这个压缩包“安卓Android源码——及时通讯源码:实时对讲机.zip”...

    Android开发精典案例60个

    在Android开发领域,掌握经典案例是提升技能的关键步骤。"Android开发精典案例60个"集合了多种实用且常见的应用场景,旨在帮助新手快速上手并深入理解Android平台的编程逻辑。以下是对这些案例的详细解析: 1. **...

    中国象棋Android版源码

    此源码集成了完整的棋局逻辑、用户交互界面以及游戏流程控制,让开发者能够深入理解Android应用程序的设计与实现过程。下面我们将详细探讨这个项目中的关键知识点。 1. **Android开发环境**:此项目基于Android ...

    Android-BookBrowser豆瓣图书信息浏览客户端

    6. **权限管理**:Android 6.0及以上版本引入了运行时权限管理,开发者需要在应用中处理相关权限申请,如INTERNET权限用于网络访问。 7. **测试与调试**:为了确保应用的稳定性和可靠性,开发者需要编写单元测试和...

    类QQ实现代码.rar_P2P_greatlyrvv_即时通讯_类QQ

    这通常涉及到了解各平台的推送服务,如iOS的APNs(Apple Push Notification service)和Android的GCM/FCM(Google Cloud Messaging/Firebase Cloud Messaging)。 10. **性能优化**: 为了提供流畅的用户体验,...

    Android应用源码科学报纸网站安卓项目.zip

    在这个名为"Android应用源码科学报纸网站安卓项目.zip"的压缩包中,我们可以找到一个完整的Android应用程序源代码,用于开发一个科学报纸网站的移动客户端。这个项目是针对Android平台的,利用了Android SDK和相关...

    基于Android的焦点新闻App开发(源码+数据库+演示视频).rar

    本资源是一个关于基于Android开发焦点新闻App的完整项目,涵盖了从设计到实现的全过程,并提供了源码、数据库和演示视频,对于学习Android应用开发的初学者或是希望提升Android项目实战经验的开发者来说,是一个非常...

    android菜谱

    了解其审核政策和提交流程,以及如何通过Google Play Services进行版本更新和用户反馈收集。 综上所述,创建一个Android菜谱应用涉及到许多技术和实践,包括但不限于前端UI设计,后端数据处理,用户体验优化,以及...

    Android学习笔记

    Android模拟器是一种软件工具,允许开发者在计算机上运行Android应用程序,无需实际的物理设备。它支持不同的屏幕尺寸和分辨率,例如: - VGA (480×640) - QVGA (240×320) - HVGA (320×480) - WQVGA (240×...

    精典源码之高仿墨迹天气.rar

    在这个压缩包中,包含了一整套实现这一目标的源代码。下面,我们将深入探讨这个项目中的关键知识点。 1. **Android开发基础**:该项目是基于Android平台开发的,因此需要对Android的基本概念有深入理解,如Activity...

Global site tag (gtag.js) - Google Analytics