首页 > 其他分享 >[原创]通过代码及流程图说明Google在Android上的Push机制的实现

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

时间:2023-06-02 21:36:51浏览次数:40  
标签:Google XMPP intent C2DM Push Android com


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

Google从FroYo版本后引入了C2DM (Cloud to Device Messaging)框架:
[url]http://code.google.com/android/c2dm/index.html[/url]
[i]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.[/i]

这个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上面了.
[img]http://dl.iteye.com/upload/attachment/408542/312798a8-fea2-301c-8c1e-0d8ff6f9f0a1.png[/img]
下面, 通过介绍Android上Google Contacts/Calendar如何利用C2DM实现Push机制来进行说明. 说的顺序可能比较乱, 大家慢慢理解, 并且其中的code只是用来帮助大家来进行理解.

[b]1. 在AndroidManifest.xml上declare了一个broadcast receiver和一个对应的service用来接收C2DM发送的通知.[/b]

<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开发文档.



[b]


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


这里用到的就是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="[email protected]" /></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(......);




大概的时序图为:



[img]http://dl.iteye.com/upload/attachment/408536/2e2403c1-aa98-35e1-865d-50b63c4f70f5.png[/img]


标签:Google,XMPP,intent,C2DM,Push,Android,com
From: https://blog.51cto.com/u_16125990/6405093

相关文章

  • Google Java编程风格指南
    作者:Hawstein目录前言源文件基础源文件结构格式命名约定编程实践Javadoc后记前言这份文档是GoogleJava编程风格规范的完整定义。当且仅当一个Java源文件符合此文档中的规则,我们才认为它符合Google的Java编程风格。与其它的编程风格指南一样,这里所讨论的不仅仅是编码格......
  • android-夜间模式
    资源1AndroidMaterialDesign系列之夜间模式阐述了夜间模式的资源文件,告知建立了values-night文件夹对于夜间模式的颜色和主题配置,我们需要建立一个res下建立一个values-night文件夹,里面放着夜间主题样式的color等资源。colors.xml配置如下:<?xmlversion="1.0"encoding="utf-8"......
  • 移动开发之设计模式-组合模式(IOS&Android)
    组合模式组合模式(CompositePattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。这种模式创建了一个包含自己对象组的类。该类提供了修改相......
  • Fragment原理解析androidx版本&ViewPager与Fragment
    资料Fragment生命周期为什么要通过Fragment.setArguments(Bundle)传递参数单独问题:动态方式,静态方式添加随Activity启动动态添加回退栈onSaveInstance静态方式添加FragmentmHost是这个finalFragmentControllermFragments=FragmentController.createController(newHostCallb......
  • 2014.4.25.12.51_context_2014.4.25_Android种的Context详解
    Android中Context详解----你所不知道的Context一、Context相关类的继承关系2二、什么时候创建Context实例5从上可知一下三点,即:1、它描述的是一个应用程序环境的信息,即上下文。2、该类是一个抽象(abstractclass)类,Android提供了该抽象类的具体实现类(后面我们会讲到是Co......
  • 2015.4.24.17.23_界面_2015.4.24__Android界面设计工具_0.01
    iOS,Android原型图设计软件–>AxureRP,UIDesigner,Pencil,iPhoneMockup,Justinmind<–#AxureRPAxureRP-快速原型制作软件–线框图,原型,规格文档,由美国AxureSoftwareSolutions,Inc.公司开发。AxureRP也分商业版和免费版,英文官方:http://www.axure.com/download中文网站:h......
  • android基础-ConstraintLayout
    资料约束布局ConstraintLayout看这一篇就够了ConstraintLayout布局居中|居右实现。ConstraintLayout中TextView文字超过屏幕问题ConstraintLayoutConstraintLayout字体超出屏幕解决方法约束布局ConstraintLayout看这一篇就够了具体的方法layout_constraintLeft_toLeftOflayout_c......
  • Android利用tcpdump抓包
    [b]Instructions[/b][url]http://source.android.com/porting/tcpdump.html[/url][b]SourceCodeandDocuments[/b][url]http://www.tcpdump.org/[/url][b]CompiledBinaryDownload[/b][url]http://www.strazzere.com/android/tcpdump[/url]......
  • android: workaround for slow ‘building workspace’ problem in eclipse
    Whiledevelopingforandroidoneclipse3.6ihadtheproblemthateachtimeisavedafile,eclipseblockedmeseveralsecondswith‘buildingworkspace…’.Similartothese:stackoverflow–android-compilation-is-slow-using-eclipsestackoverflow–android-......
  • Angular Google Charts教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介GoogleCharts是一个纯粹的基于JavaScript的图表库,旨在通过添加交互式图表功能来增强Web应用程序.它支持各种图表.在Chrome,Firefox,Safari,InternetExplorer(IE)等标准浏览器中使用SVG绘制图表.在传统的IE6中,VML用于绘制图形.AngularGoogleCharts是一个基于开源角度......