当前位置:奇幻城娱乐网址 > 母婴 > 云端推送,实现Android消息推送

云端推送,实现Android消息推送

文章作者:母婴 上传时间:2019-09-30

MIME-version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_0076_01C29953.BE473C30"; type="text/html" X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 This is a multi-part message in MIME format. ------=_NextPart_000_0076_01C29953.BE473C30 Content-Type: text/html; Content-Transfer-Encoding: quoted-printable Content-Location: file:///~tmp1363935081.TMP.html GCM学习

 
点击“Create project”按键后,将引导你创建第一个项目。如果之前有创建项目,将不会看到这个提示,你看到的会是一个面板。点击左上角的下拉菜单,选择“Other projects”-"Create",将会引导你创建一个项目,你的浏览器地址将会形如:

一、基础知识

最近在网上查了关于很多Android消息推送的资料,其中主要有四种方法。

GCM学习

第二:激活你的GCM服务。

当我们开发需要和服务器交互的应用程序时,基本上都需要获取服务器端的数据,比如《地震及时通》就需要及时获取服务器上最新的地震信息。要获取服务器上不定时更新的信息一般来说有两种方法,第一种是客户端使用Pull(拉)的方式,隔一段时间就去服务器上获取信息,看是否有更新的信息出现。第二种就是服务器使用Push(云端推送)的方式,当服务器端有新信息了,则把最新的信息Push到客户端上。

1) 使用GCM服务(Google Cloud Messaging) 2) 使用XMPP协议(Openfire + Spark + Smack) 3) 使用MQTT协议 4) 使用HTTP轮循方式

 

在谷歌Api控制台页面中,选中“Services”项,打开“Google Cloud Messaging for Android”项中的开关并接受协议,激活你账号下的GCM服务。

虽然Pull和Push两种方式都能实现获取服务器端更新信息的功能,但是明显来说Push is better than pull。因为Pull方式不仅浪费客户端的流量,而且更浪费电量。

以上这四种方法的优缺点大家都可以到网上搜到,这里提供一个参考的连接:  在这里我将使用GCM服务(Google Cloud Messaging)来实现Android消息的推送。 注:本人已实现该推送功能,不过有些限制条件。

google教程

第三:获得API Key

Android从2.2版本开始增加了Cloud to Device Messaging(C2DM)框架,在系统中支持了Push功能,基于Android平台使用Push功能更加简单了。虽然C2dm目前还处在实验室阶段,不过小规模的使用是没有问题的。

Google Cloud Messaging推送消息流程:这里我就稍微提下,我们从自己的服务器上发送消息到google的服务器上,在通过google的服务器推送出去,具体的实现细节我也不深究了,也许有人就会问为什么要通过google的服务器推送呢,直接从自己的服务器上推送过去就好了;在此之前我也考虑过,可是中间有太多的实现细节,说实话楼主也不是很懂,所以也就妥协了.....

还是在控制台页面,选中“API Access”。点击“Create New Server Key”,在接下来的界面中直接点“Create”,将会生成一个Api Key,这个Api Key将用来验证发送方。

下面我们就来感受一下Android的C2dm功能。

实现该推送功能的必备条件: 1)你的SDK需要从SDK Manager里安装Google Cloud Messaging for Android Library,安装步骤:启动SDK Manager->Extras->勾选Google Cloud Messaging for Android Library这一项,然后安装就可以了。 2)你用来调试的模拟器或是真机必须支持Google APIs,比如说你用模拟器调试的话,在新建模拟器的时候“target”这一项要选择Google APIs,版本要高于2.2。 3)gcm.jar文件,等你执行完第一步的时候,你就可以在你的Android SDK目录下的extrasgooglegcmsamplesgcm-demo-clientlibs目录里找到这个文件,把它复制到你的项目的libs目录下,并添加路径。 4)你的模拟器或是真机必须设置并且登入一个google账户,比如你在调试的时候出现ACCOUNT_MISSING错误提示,说明就是没有登入google的帐号。 5)你的耐心。。。。。。 6)如果前面五点你都具备了,请往下看.......

1.创建项目

第四,你的电脑需要具有GCM服务所必须的一些包。这些包可以在Android SDK Manager中下载安装,更新的包名叫Google Cloud Messaging for Android,在Extras展开项中。安装完后,在sdk所在目录extrasgooglegcm中,在这里你会看到gcm的发送、接收等操作使用到的工具类和包都有在这里面。

二、C2DM框架

下面我将一一介绍我实现的步骤: 1. 注册用户,得到Project Number和APP key,Project Number就是我们在后面编程时候所要用到的SENDER_ID 。开启Google Cloud Messaging for Chrome服务。

2.在Services中开启 Google Cloud Messaging for Android

你可以用eclipse直接import这些项目,并导入里面的几个包,基于这些类文件,我们创建对它们的调用。以上,准备工作已经完毕。下面我们开始讲讲怎么使用。(注:准备工作中,如果安卓设备没有Google Play Services包,还需要另外增加第5步,自己去下载谷歌play的服务包并安装到手机/平板中)

使用Android的C2DM功能有几个要求:

图片 1

3.Create an OAuth 2.0 client ID

需要注意的是,GMC的方式并没有严格的客户端和服务端的,只要求接收消息的是安卓应用,而发送消息的一方可以是任意程序。可以在你自己搭建的服务器里,可以是同一个安卓应用里,也可以只是一个main函数。不过需要使用到的类和环境就要分别搭建好了。

  1. 需要Android2.2及以上的系统版本。
  2. 使用C2DM功能的Android设备上需要设置好Google的账户。
    3. 需要在这里注册使用C2DM功能的用户邮箱账号(最好为C2DM单独注册一个Gmail邮箱账号)。

 

4.API Access 创建 Server Key 和 Android Key

使用GCMRegistrar和Sender这两个类可以分别实现客户端的注册和发送消息的功能。这两个类就在我们刚才下载的gcm服务包中。(在谷歌play服务包google-play-services.jar包中,有一个GoogleCloudMessaging的类,也可以提供注册客户端和发送消息的方法。不过看了官方文档,和前一种方式差不多。这里先不讲这种方法了。)

接下来我们来看下C2dm的完整过程,这里借用一下Google官方推出的Chrome To Phone过程图来说明下。

a) 注册完后点击左侧的Overview后,我们在右边就可以看到Project Number,如上图。

在androidManifest.xml中加入

 

图片 2
图1 C2DM操作过程图

图片 3

<permission

以上完成了开始的准备工作。接下来讲代码的实现:

要使用C2DM来进行Push操作,基本上要使用以下6个步骤:

 

android:name=3D"com.myb.app.permission.C2D_MESSAGE"

 

1、注册:Android设备把使用C2DM功能的用户账户(比如android.c2dm.demo@gmail.com)和App名称发送给C2DM服务器。

b) 同样,我们点击左边的API Access就可以看到API key,如上图红线的地方;如果你没有API Key,你可以点击红线部分的“Create new Server key...”来创建一个API key。

android:protectionLevel=3D"signature" />

先讲客户端注册服务。首先要在AndroidManifest.xml文件里面添加3个GCM/C2DM的权限和必要的网络访问等权限。完整的文件在后面给出。

2、C2dm服务器会返回一个registration_id值给Android设备,设备需要保存这个registration_id值。

c) 其次我们要开启Google Cloud Messaging for Android服务,点击页面左边的“Services”,在右边的下面我们就可以找到Google Cloud Messaging for Android项,开启它。如下图。

<uses-permission android:name=3D"com.myb.app.permission.C2D_MESSAGE" />

 

3、Android设备把获得的registration_id和C2DM功能的用户账户(android.c2dm.demo@gmail.com)发送给自己的服务器,不过一般用户账户信息因为和服务器确定好的,所以不必发送。

图片 4

 

然后创建一个名为GCMIntentService的android服务,并且继承GCMBaseIntentService这个抽象类并实现里面的几个方法,记得在配置文件里面要申明service。尤其要注意的是,这个service一定要命名为GCMIntentService,并且放到应用包名下。因为GCM的机制会默认使用到这个服务,并且没有提供可以设置为其它服务代替它的方法。

这样Android设备就完成了C2DM功能的注册过程,接下来就可以接收C2DM服务器Push过来的消息了。

2.现在我们就要建立自己的服务器了(PS:别听到服务器就害怕,这里只是建立一个小小的网站式服务器)。官网有两种方式简历服务器,我采用的是App Engine for Java这个方法,具体可以参考:。  这里我讲讲我是怎用App Engine for Java建立发送消息的服务器的。APP Engine for Java的下载地址: App Engine for Java a)在你安装Google Cloud Messaging for Android Library后,你的Android SDK目录下有一个extras/google/目录,其中包含的目录有gcm-client, gcm-server, samples/gcm-demo-client, samples/gcm-demo-server和samples/gcm-demo-appengine. b)进入samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/这个目录,找到ApiKeyInitializer.java这个文件,用文本编辑器打开,找到replace_this_text_by_your_Simple_API_Access_key这句话,并用你的注册时得到的APP key替换它,保存。 c)打开dos窗口,开始->运行,在dos窗口下进入 samples/gcm-demo-appengine目录,在dos中输入ant -Dsdk.dir=D:appengine-java-sdk runserver -Dserver.host=192.168.1.10 注:这里的-Dsdk.dir=D:appengine-java-sdk要根据自己的实际情况来,-Dsdk.dir就是你存放appengine-java-sdk的目录,而-Dserver.host就是你自己电脑的IP。 d)以上步骤你都没出错的话,就可以打开浏览器输入:

//其中com.myb.app改为相应的包名

GCMIntentService类:

4、服务器获得数据。这里图中的例子Chrome To Phone,服务器接收到Chrome浏览器发送的数据。数据也可以是服务器本地产生的。这里的服务器是Google AppEngine(很好的一项服务,可惜在国内被屏了),要换成自己的服务器。服务器还要获取注册使用C2DM功能的用户账户(android.c2dm.demo@gmail.com)的ClientLogin权限Auth。

图片 5

<!-- App receives GCM messages. -->

[java]
public class GCMIntentService extends GCMBaseIntentService { 
    public static final String SENDERID = "812216982441"; 
     
    public GCMIntentService(){ 
        super(SENDERID); 
    } 
 
    @Override 
    protected void onError(Context arg0, String arg1) { 
        Log.v("GCMIntentService", "onError错误"); 
    } 
 
    @Override 
    protected void onMessage(Context arg0, Intent arg1) { 
        Log.v("GCMIntentService", "收到新消息:"+arg1.getStringExtra("mine")); 
        final String info = arg1.getStringExtra("mine"); 
        Handler handler = new Handler(Looper.getMainLooper()); 
        handler.post(new Runnable() { 
             
            @Override 
            public void run() { 
                Toast.makeText(getBaseContext(), "收到新消息:"+info, Toast.LENGTH_LONG).show(); 
            } 
        }); 
    } 
 
    @Override 
    protected void onRegistered(Context arg0, String arg1) { 
        Log.v("GCMIntentService", "onRegistered注册完成"); 
    } 
 
    @Override 
    protected void onUnregistered(Context arg0, String arg1) { 
        Log.v("GCMIntentService", "onUnregistered注销注册"); 
    } 
 

5、服务器把要发送的数据和registration_id一起,并且头部带上获取的Auth,使用POST的方式发送给C2dm服务器。

3.下面我们可以开始着手写Android的客户端程序了,在文章的最后我会提供源码的下载地址。

<uses-permission android:name=3D"com.google.android.c2dm.permission.RECEIVE" />

public class GCMIntentService extends GCMBaseIntentService {
 public static final String SENDERID = "812216982441";
 
 public GCMIntentService(){
  super(SENDERID);
 }

6、C2DM服务器会以Push的方式把数据发送给对应的Android设备,Android设备只要在程序中按之前和服务器商量好的格式从对应的key中获取数据即可。

a)根据官网,我们可以知道首先要给程序添加依稀权限。添加权限大家可以参考:

<!-- GCM connects to Google Services. -->

 @Override
 protected void onError(Context arg0, String arg1) {
  Log.v("GCMIntentService", "onError错误");
 }

这样我们就大概明白了C2dm的工作流程,下面我们就结合一个实例来具体的说明以上6个步骤。

[html] view plaincopy

<uses-permission android:name=3D"android.permission.INTERNET" />

 @Override
 protected void onMessage(Context arg0, Intent arg1) {
  Log.v("GCMIntentService", "收到新消息:"+arg1.getStringExtra("mine"));
  final String info = arg1.getStringExtra("mine");
  Handler handler = new Handler(Looper.getMainLooper());
  handler.post(new Runnable() {
   
   @Override
   public void run() {
    Toast.makeText(getBaseContext(), "收到新消息:"+info, Toast.LENGTH_LONG).show();
   }
  });
 }

三.实例开发

  1. <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="xx"/>  

<!-- GCM requires a Google account. -->

 @Override
 protected void onRegistered(Context arg0, String arg1) {
  Log.v("GCMIntentService", "onRegistered注册完成");
 }

我们要创建的程序名称为AndroidC2DMDemo,包名为com.ichliebephone.c2dm。

[html] view plaincopy

<uses-permission android:name=3D"android.permission.GET_ACCOUNTS" />

 @Override
 protected void onUnregistered(Context arg0, String arg1) {
  Log.v("GCMIntentService", "onUnregistered注销注册");
 }

开始之前我们先去C2DM网页上注册一下使用C2DM功能的用户账户。

  1. <permission android:name="my_app_package.permission.C2D_MESSAGE" android:protectionLevel="signature" />  
  2. <uses-permission android:name="my_app_package.permission.C2D_MESSAGE" />   

<!-- Keeps the processor from sleeping when a message is received. -->

}
这几个方法是结合了GCM的机制的,注意不要误解成了它们是安卓的service的。

图片 6
图2 应用程序名

[html] view plaincopy

<uses-permission android:name=3D"android.permission.WAKE_LOCK" />

onError:在注册客户端或者解除注册出错时调用。
onMessage:客户端收到消息时调用。

其中应用程序名要填写带包名的完整名称,比如这里为om.ichliebephone.c2dm. AndroidC2DMDemo。

  1. <!-- App receives GCM messages. -->  
  2. <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />  
  3. <!-- GCM connects to Google Services. -->  
  4. <uses-permission android:name="android.permission.INTERNET" />   
  5. <!-- GCM requires a Google account. -->  
  6. <uses-permission android:name="android.permission.GET_ACCOUNTS" />  
  7. <!-- Keeps the processor from sleeping when a message is received. -->  
  8. <uses-permission android:name="android.permission.WAKE_LOCK" />  

 

onRegistered:注册完成。

图片 7
图3 C2DM用户账户注册

[html] view plaincopy

<receiver

onUnregistered:解除注册完成。

这里的contact邮箱使用一个你能接收到邮件的邮箱即可,下面的Role(sender)account邮箱最好单独注册一个Gmail邮箱来使用C2DM服务。我们这里使用的是专门注册的android.c2dm.deno@gmail.com邮箱。

  1. <receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >  
  2.   <intent-filter>  
  3.     <action android:name="com.google.android.c2dm.intent.RECEIVE" />  
  4.     <action android:name="com.google.android.c2dm.intent.REGISTRATION" />  
  5.     <category android:name="my_app_package" />  
  6.   </intent-filter>  
  7. </receiver>  

android:name=3D"com.google.android.gcm.GCMBroadcastReceiver"

“常量”SENDERID是前面在控制台页面创建项目时得到的那个值。

提交后,过一段时间就会收到Google发送过来的确认邮件,然后你就可以使用C2DM的Push服务了。

[html] view plaincopy

android:permission=3D"com.google.android.c2dm.permission.SEND" >

建好服务类后就可以开始注册了。以下是注册的代码片段,直接在Activit的onCreate方法里执行就可以。

介绍了这么多,我们先来快速完成一个实例,只完成Android设备端的注册部分,不包含向服务器发送registration_id和服务器向C2DM服务器发送数据的具体代码,这部分只是用Ubuntu下的curl命令来模拟,主要是快速亲自体验一下Push的结果。

  1. <service android:name=".GCMIntentService" />  

<intent-filter>

[java] view plaincopyprint?protected void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.activity_main); 
         
        GCMRegistrar.checkDevice(this); 
        GCMRegistrar.checkManifest(this); 
        final String regId = GCMRegistrar.getRegistrationId(this); 
        if (regId.equals("")) { 
          GCMRegistrar.register(this, GCMIntentService.SENDERID); 
          Log.v(TAG, "新设备:"+GCMRegistrar.isRegistered(this)+GCMRegistrar.getRegistrationId(this)); 
        } else { 
          Log.v(TAG, "Already registered"); 
        } 
        //点击后解除注册,不接收消息  
        Button btn = (Button) findViewById(R.id.unregist_btn); 
        btn.setOnClickListener(new OnClickListener() { 
             
            @Override 
            public void onClick(View v) { 
                GCMRegistrar.unregister(getBaseContext()); 
            } 
        }); 
         
    } 

创建一个Android工程AndroidC2DMDemo,并且包含进Google的开源例子Chrome To Phone中的c2dm包com.google.android.c2dm,包中包含三个Java类,分别为:

b)完成类GCMIntentService的编写,该类必须继承GCMBaseIntentService,在这里我们需要完成的方法有: --onRegistered(Context context, String regId) --onUnregistered(Context context, String regId) --onMessage(Context context, Intent intent) --onError(Context context, String errorId) --onRecoverableError(Context context, String errorId) 在onCreate方法里我们需要添加以下语句:

<action android:name=3D"com.google.android.c2dm.intent.RECEIVE" />

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  GCMRegistrar.checkDevice(this);
  GCMRegistrar.checkManifest(this);
  final String regId = GCMRegistrar.getRegistrationId(this);
  if (regId.equals("")) {
    GCMRegistrar.register(this, GCMIntentService.SENDERID);
    Log.v(TAG, "新设备:"+GCMRegistrar.isRegistered(this)+GCMRegistrar.getRegistrationId(this));
  } else {
    Log.v(TAG, "Already registered");
  }
  //点击后解除注册,不接收消息
  Button btn = (Button) findViewById(R.id.unregist_btn);
  btn.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    GCMRegistrar.unregister(getBaseContext());
   }
  });
  
 }
checkDevice()检查系统版本和是否装有google service frame,否则抛出异常。(GCM服务需要安装有谷歌服务包,且系统版本2.2及以上的才支持)

第一个类为C2DMBaseReceiver:

[java] view plaincopy

<action android:name=3D"com.google.android.c2dm.intent.REGISTRATION" />

checkManifest()检查AndroidManifest.xml文件是否有配置有必须的权限,和检测广播接收器是否有正确的权限和过滤器,是否可以正常接收广播。否则抛出异常。

package com.google.android.c2dm;

  1. GCMRegistrar.checkDevice(this);  
  2. GCMRegistrar.checkManifest(this);  
  3. final String regId = GCMRegistrar.getRegistrationId(this);  
  4. if (regId.equals("")) {  
  5.   GCMRegistrar.register(this, SENDER_ID);  
  6. } else {  
  7.   Log.v(TAG, "Already registered");  
  8. }  

<category android:name=3D"com.myb.app" />

register()真正开始注册一个GCM服务,它会启动一个action名为com.google.android.c2dm.intent.REGISTER的服务。注意这个才是真正的GCM服务,而前面我们自己创建的那个其实并不是GCM服务,只是GCM整个服务机制里面为我们提供的一个业务上的回调而已。

 

c)其实在我们安装完Google Cloud Messaging for Android Library后里面就有一个目录trasgooglegcmsamplesgcm-demo-client,这里就有Android客户端的源码,只是我们需要做些修改,我们需要修改目录samples/gcm-demo-client/src/com/google/android/gcm/demo/app下的CommonUtilities.java 里的SENDER_ID 和SERVER_URL。修改如下:

</intent-filter>

完整的AndroidManifest.xml文件:

import java.io.IOException;

[java] view plaincopy

</receiver>

[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> 
<manifest 
    xmlns:android="" 
    package="com.ives.androidgcmclient" 
    android:versionCode="1" 
    android:versionName="1.0"> 
    <uses-sdk 
        android:minSdkVersion="8" 
        android:targetSdkVersion="15"/> 
    <permission 
        android:name="com.ives.androidgcmclient.permission.C2D_MESSAGE" 
        android:protectionLevel="signature"/> 
    <uses-permission 
        android:name="com.ives.androidgcmclient.permission.C2D_MESSAGE"/> 
    <uses-permission 
        android:name="com.google.android.c2dm.permission.RECEIVE"/> 
    <uses-permission 
        android:name="android.permission.INTERNET"/> 
    <uses-permission 
        android:name="android.permission.GET_ACCOUNTS"/> 
    <uses-permission 
        android:name="android.permission.WAKE_LOCK"/> 
    <uses-permission 
        android:name="android.permission.CHANGE_NETWORK_STATE"> 
    </uses-permission> 
    <uses-permission 
        android:name="android.permission.CHANGE_WIFI_STATE"> 
    </uses-permission> 
    <uses-permission 
        android:name="android.permission.ACCESS_NETWORK_STATE"> 
    </uses-permission> 
    <uses-permission 
        android:name="android.permission.ACCESS_WIFI_STATE"/> 
    <application 
        android:allowBackup="true" 
        android:icon="@drawable/ic_launcher" 
        android:label="@string/app_name" 
        android:theme="@style/AppTheme"> 
        <activity 
            android:name="com.ives.androidgcmclient.MainActivity" 
            android:label="@string/app_name"> 
            <intent-filter> 
                <action 
                    android:name="android.intent.action.MAIN"/> 
 
                <category 
                    android:name="android.intent.category.LAUNCHER"/> 
            </intent-filter> 
        </activity> 
 
        <receiver 
            android:name="com.google.android.gcm.GCMBroadcastReceiver" 
            android:permission="com.google.android.c2dm.permission.SEND"> 
            <intent-filter> 
                <action 
                    android:name="com.google.android.c2dm.intent.RECEIVE"/> 
                <action 
                    android:name="com.google.android.c2dm.intent.REGISTRATION"/> 
                <category 
                    android:name="com.ives.androidgcmclient"/> 
            </intent-filter> 
        </receiver> 
        <service 
            android:name=".GCMIntentService"/> 
    </application> 
 
</manifest> 

import android.app.AlarmManager;

  1. static final String SERVER_URL = "";  
  2. static final String SENDER_ID = "4815162342";  

 

<?xml version="1.0" encoding="utf-8"?>
<manifest
 xmlns:android=""
 package="com.ives.androidgcmclient"
 android:versionCode="1"
 android:versionName="1.0">
 <uses-sdk
  android:minSdkVersion="8"
  android:targetSdkVersion="15"/>
 <permission
  android:name="com.ives.androidgcmclient.permission.C2D_MESSAGE"
  android:protectionLevel="signature"/>
 <uses-permission
  android:name="com.ives.androidgcmclient.permission.C2D_MESSAGE"/>
 <uses-permission
  android:name="com.google.android.c2dm.permission.RECEIVE"/>
 <uses-permission
  android:name="android.permission.INTERNET"/>
 <uses-permission
  android:name="android.permission.GET_ACCOUNTS"/>
 <uses-permission
  android:name="android.permission.WAKE_LOCK"/>
 <uses-permission
  android:name="android.permission.CHANGE_NETWORK_STATE">
 </uses-permission>
 <uses-permission
  android:name="android.permission.CHANGE_WIFI_STATE">
 </uses-permission>
 <uses-permission
  android:name="android.permission.ACCESS_NETWORK_STATE">
 </uses-permission>
 <uses-permission
  android:name="android.permission.ACCESS_WIFI_STATE"/>
 <application
  android:allowBackup="true"
  android:icon="@drawable/ic_launcher"
  android:label="@string/app_name"
  android:theme="@style/AppTheme">
  <activity
   android:name="com.ives.androidgcmclient.MainActivity"
   android:label="@string/app_name">
   <intent-filter>
    <action
     android:name="android.intent.action.MAIN"/>

import android.app.IntentService;

注:这里的SERVER_URL和SENDER_ID要根据你自己的实际情况来,到这里我们的程序就基本写完了。下面就就可以运行进行调试了...... 当你启动模拟器或是真机并且以上步骤都没错的话,再次向浏览器中输入

 

    <category
     android:name="android.intent.category.LAUNCHER"/>
   </intent-filter>
  </activity>

import android.app.PendingIntent;

图片 8

 

  <receiver
   android:name="com.google.android.gcm.GCMBroadcastReceiver"
   android:permission="com.google.android.c2dm.permission.SEND">
   <intent-filter>
    <action
     android:name="com.google.android.c2dm.intent.RECEIVE"/>
    <action
     android:name="com.google.android.c2dm.intent.REGISTRATION"/>
    <category
     android:name="com.ives.androidgcmclient"/>
   </intent-filter>
  </receiver>
  <service
   android:name=".GCMIntentService"/>
 </application>

import android.content.Context;

4.这里楼主提供Android客户端程序的下载地址,服务器还需自己配置,下载地址:GCM-Demo 注:此博文也是楼主根据官网总结出来的,难免有错,大家勿喷,如果大家有更好的方法,欢迎拿出来分享。 PS:希望大家下载了源码后能耐下心来看看,要知其然还要知其所以然。 最后,希望大家尊重劳动者的成果,在转载的时候加上本文链接:

<service android:name=3D".GCMIntentService" />

</manifest>

import android.content.Intent;

 

import android.os.PowerManager;

在android SdK extrasgooglegcmgcm-clientdist 找到 gcm.jar,加入项目中

import android.util.Log;

 

 

向google服务器注册服务

/**

 

 * Base class for C2D message receiver. Includes constants for the

/***

 * strings used in the protocol.

 * 向google注册服务

 */

 */

/**

private void GcmRegistrarDevice() {

 * 接收和处理C2DM消息的基类

GCMRegistrar.checkDevice(this);

 * */

GCMRegistrar.checkManifest(this);

public abstract class C2DMBaseReceiver extends IntentService {

final String regId =3D GCMRegistrar.getRegistrationId(this);

    // 和C2DM Push的Intent内容相关

if (regId.equals("")) {

    // 重新向C2DM服务器注册

  GCMRegistrar.register(this, SENDER_ID);

    private static final String C2DM_RETRY = "com.google.android.c2dm.intent.RETRY";

} else {

    // 向C2DM服务器注册后的回调处理

  Log.v(TAG, "Already registered:" + regId);

    public static final String REGISTRATION_CALLBACK_INTENT = "com.google.android.c2dm.intent.REGISTRATION";

}

    // 接收到C2DM服务器的推送消息

}

    private static final String C2DM_INTENT = "com.google.android.c2dm.intent.RECEIVE";

 

 

SENDER_ID 为创建的google项目的 project ID,

    // Logging tag

创建 GCMIntentService 类,从 GCMBaseIntentService 继承 接受注册的GCM发回的信息

    private static final String TAG = "C2DM";

 

 

package com.myb.app;

    // Extras in the registration callback intents.

 

    // 向C2DM注册返回的intent中包含的key

import android.app.Notification;

    public static final String EXTRA_UNREGISTERED = "unregistered";

import android.app.NotificationManager;

    public static final String EXTRA_ERROR = "error";

import android.app.PendingIntent;

    public static final String EXTRA_REGISTRATION_ID = "registration_id";

import android.content.Context;

    // 向C2DM注册出错的原因

import android.content.Intent;

    public static final String ERR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE";

import android.util.Log;

    public static final String ERR_ACCOUNT_MISSING = "ACCOUNT_MISSING";

 

    public static final String ERR_AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED";

import com.google.android.gcm.GCMBaseIntentService;

    public static final String ERR_TOO_MANY_REGISTRATIONS = "TOO_MANY_REGISTRATIONS";

 

    public static final String ERR_INVALID_PARAMETERS = "INVALID_PARAMETERS";

public class GCMIntentService extends GCMBaseIntentService{

    public static final String ERR_INVALID_SENDER = "INVALID_SENDER";

private final static String TAG =3D GCMIntentService.class.getSimpleName();

    public static final String ERR_PHONE_REGISTRATION_ERROR = "PHONE_REGISTRATION_ERROR";

 

 

private NotificationManager mNM;

    // wakelock

 

    private static final String WAKELOCK_KEY = "C2DM_LIB";

@Override

 

public void onCreate() {

    private static PowerManager.WakeLock mWakeLock;

super.onCreate();

    private final String senderId;

 

 

mNM =3D (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

    /**

}

     * The C2DMReceiver class must create a no-arg constructor and pass the

 

     * sender id to be used for registration.

@Override

     */

protected void onError(Context arg0, String arg1) {

    public C2DMBaseReceiver(String senderId) {

Log.d(TAG, "onError:" + arg1);

        // senderId is used as base name for threads, etc.

}

        super(senderId);

 

        this.senderId = senderId;

@Override

    }

protected void onMessage(Context arg0, Intent intent) {

 

Log.e("GCM MESSAGE", "Message Recieved!!!");

    // 下面几个是接收到C2DM Push过来的信息后的回调函数,都可以在继承的子类中处理

        String message = intent.getStringExtra("message");

    /**

        if (message == null) {

     * Called when a cloud message has been received.

            Log.e("NULL MESSAGE", "Message Not Recieved!!!");

     */

        } else {

    /**

            Log.i(TAG, "new message=3D " + message);

     * 接收到C2DM服务器Push的消息后的回调函数,需要在继承的子类中处理

            showNotifiy(message);

     * */

        }

    protected abstract void onMessage(Context context, Intent intent);

}

 

 

    /**

@Override

     * Called on registration error. Override to provide better error messages.

protected void onRegistered(Context arg0, String arg1) {

     * 

Log.d(TAG, "onRegistered:" + arg1);

     * This is called in the context of a Service - no dialog or UI.

}

     */

 

    /**

@Override

     * 出错的回调函数

protected void onUnregistered(Context arg0, String arg1) {

     * */

Log.d(TAG, "onUnregistered:" + arg1);

    public abstract void onError(Context context, String errorId);

}

 

 

    /**

 

     * Called when a registration token has been received.

private void showNotifiy(String msg){

     */

Intent intent =3D new Intent(this, HomeActivity.class);

    /**

PendingIntent contentIntent =3D PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

     * 注册后的回调函数

String tickerText =3D getString(R.string.app_name, msg);

     * */

 

    public void onRegistered(Context context, String registrationId)

// construct the Notification object.

            throws IOException {

Notification notif = new Notification(R.drawable.ic_logo, tickerText, System.currentTimeMillis());

        // registrationId will also be saved

notif.setLatestEventInfo(this, "母婴宝", msg, contentIntent);

    }

notif.defaults = Notification.DEFAULT_ALL;

 

mNM.notify(R.string.app_name, notif);

    /**

}

     * Called when the device has been unregistered.

 

     */

}

    /**

 

     * 取消注册的回调函数

后台,我们的后台使用的是maven+spring mvc+jpa, 如果不是maven管理项目则把Android SDK 下面的xtrasgooglegcmgcm-serverdist 中的 gcm-server.jar加入项目。如果是maven,github上有人做了处理

     * */

 

    public void onUnregistered(Context context) {

    }

 

 

 

    // IntentService的方法

在pom.xml中加入

    @Override

 

    public final void onHandleIntent(Intent intent) {

 

        try {

<repository>

            Context context = getApplicationContext();

    <id>gcm-server-repository</id>

            if (intent.getAction().equals(REGISTRATION_CALLBACK_INTENT)) {

    <url>;

                handleRegistration(context, intent);// 处理注册后的回调

</repository>

            } else if (intent.getAction().equals(C2DM_INTENT)) {

 

                onMessage(context, intent);// 处理C2DM Push消息的回调

<dependency>

            } else if (intent.getAction().equals(C2DM_RETRY)) {

    <groupId>com.google.android.gcm</groupId>

                C2DMessaging.register(context, senderId); // 重新注册

    <artifactId>gcm-server</artifactId>

            }

    <version>1.0.2</version>

        } finally {

</dependency>

            // Release the power lock, so phone can get back to sleep.

 

            // The lock is reference counted by default, so multiple

向注册的设备发送消息

            // messages are ok.

 

 

Sender sender = new Sender(myApiKey);

            // If the onMessage() needs to spawn a thread or do something else,

Message message = new Message.Builder().addData("message", msg).build();

            // it should use it's own lock.

MulticastResult mr = sender.send(message, devices, 5);

            mWakeLock.release();

for(Result result : mr.getResults()){

        }

  if (result.getMessageId() != null) {

    }

    String regId = result.getCanonicalRegistrationId();

 

    String error = result.getErrorCodeName();

    /**

    if (error.equals(Constants.ERROR_NOT_REGISTERED)) {

     * Called from the broadcast receiver. Will process the received intent,

      // application has been removed from device - unregister

     * call handleMessage(), registered(), etc. in background threads, with a

      // database

     * wake lock, while keeping the service alive.

      phoneDao.delete(regId);

     */

    }

    static void runIntentInService(Context context, Intent intent) {

  }

        if (mWakeLock == null) {

}

            // This is called from BroadcastReceiver, there is no init.

 

            PowerManager pm = (PowerManager) context

当前项目的API key

                    .getSystemService(Context.POWER_SERVICE);

devices 用户设备的注册ID,在客户端可以得到,这个值应该保存到后台

            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,

 

                    WAKELOCK_KEY);

        }

        mWakeLock.acquire();

 

        // Use a naming convention, similar with how permissions and intents are

        // used. Alternatives are introspection or an ugly use of statics.

        String receiver = context.getPackageName() + ".C2DMReceiver";

        intent.setClassName(context, receiver);

 

        context.startService(intent);

 

    }

 

    // 处理注册后的回调

    private void handleRegistration(final Context context, Intent intent) {

        final String registrationId = intent

                .getStringExtra(EXTRA_REGISTRATION_ID);

        String error = intent.getStringExtra(EXTRA_ERROR);

        String removed = intent.getStringExtra(EXTRA_UNREGISTERED);

        Log.v(TAG, "handleRegistration");

        // 打印出接收到的registraton_id

        Log.v(TAG, "dmControl: registrationId = " + registrationId

                + ", error = " + error + ", removed = " + removed);

        if (Log.isLoggable(TAG, Log.DEBUG)) {

            Log.d(TAG, "dmControl: registrationId = " + registrationId

                    + ", error = " + error + ", removed = " + removed);

        }

        if (removed != null) {

            // Remember we are unregistered

            C2DMessaging.clearRegistrationId(context);

            onUnregistered(context);

            return;

        } else if (error != null) {

            // we are not registered, can try again

            C2DMessaging.clearRegistrationId(context);

            // Registration failed

            Log.e(TAG, "Registration error " + error);

            onError(context, error);

            if ("SERVICE_NOT_AVAILABLE".equals(error)) {

                long backoffTimeMs = C2DMessaging.getBackoff(context);

 

                Log.d(TAG, "Scheduling registration retry, backoff = "

                        + backoffTimeMs);

                Intent retryIntent = new Intent(C2DM_RETRY);

                PendingIntent retryPIntent = PendingIntent

                        .getBroadcast(context, 0 /* requestCode */, retryIntent,

                                0 /* flags */);

 

                AlarmManager am = (AlarmManager) context

                        .getSystemService(Context.ALARM_SERVICE);

                am.set(AlarmManager.ELAPSED_REALTIME, backoffTimeMs,

                        retryPIntent);

 

                // Next retry should wait longer.

                backoffTimeMs *= 2;

                C2DMessaging.setBackoff(context, backoffTimeMs);

            }

        } else {

            try {

                onRegistered(context, registrationId);

                C2DMessaging.setRegistrationId(context, registrationId);

            } catch (IOException ex) {

                Log.e(TAG, "Registration error " + ex.getMessage());

            }

        }

    }

}

第二个类为C2DMBroadcastReceiver:

package com.google.android.c2dm;

 

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

 

/**

 * Helper class to handle BroadcastReciver behavior.

 * - can only run for a limited amount of time - it must start a real service 

 * for longer activity

 * - must get the power lock, must make sure it's released when all done.

 * 

 */

/**

 * 帮助类,帮忙处理BroadcastReciver过程

 * */

public class C2DMBroadcastReceiver extends BroadcastReceiver {

 

    @Override

    public final void onReceive(Context context, Intent intent) {

        // To keep things in one place.

        C2DMBaseReceiver.runIntentInService(context, intent);

        setResult(Activity.RESULT_OK, null /* data */, null /* extra */);

    }

}

第三个类为C2DMessaging:

package com.google.android.c2dm;

 

import android.app.PendingIntent;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.content.SharedPreferences.Editor;

 

/**

 * Utilities for device registration.

 *

 * Will keep track of the registration token in a private preference.

 */

/**

 * 和注册相关的一些实用函数

 * */

public class C2DMessaging {

    public static final String EXTRA_SENDER = "sender";

    public static final String EXTRA_APPLICATION_PENDING_INTENT = "app";

    public static final String REQUEST_UNREGISTRATION_INTENT = "com.google.android.c2dm.intent.UNREGISTER";

    public static final String REQUEST_REGISTRATION_INTENT = "com.google.android.c2dm.intent.REGISTER";

    public static final String LAST_REGISTRATION_CHANGE = "last_registration_change";

    public static final String BACKOFF = "backoff";

    public static final String GSF_PACKAGE = "com.google.android.gsf"; // GSF为GoogleServicesFramework.apk的缩写

 

    // package

    static final String PREFERENCE = "com.google.android.c2dm";

 

    private static final long DEFAULT_BACKOFF = 30000;

 

    /**

     * Initiate c2d messaging registration for the current application

     */

    public static void register(Context context, String senderId) {

        Intent registrationIntent = new Intent(REQUEST_REGISTRATION_INTENT);

        registrationIntent.setPackage(GSF_PACKAGE);

        registrationIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT,

                PendingIntent.getBroadcast(context, 0, new Intent(), 0));

        registrationIntent.putExtra(EXTRA_SENDER, senderId);

        context.startService(registrationIntent);

        // TODO: if intent not found, notification on need to have GSF

    }

 

    /**

     * Unregister the application. New messages will be blocked by server.

     */

    public static void unregister(Context context) {

        Intent regIntent = new Intent(REQUEST_UNREGISTRATION_INTENT);

        regIntent.setPackage(GSF_PACKAGE);

        regIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT,

                PendingIntent.getBroadcast(context, 0, new Intent(), 0));

        context.startService(regIntent);

    }

 

    /**

     * Return the current registration id.

     * 

     * If result is empty, the registration has failed.

     * 

     * @return registration id, or empty string if the registration is not

     *         complete.

     */

    public static String getRegistrationId(Context context) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        String registrationId = prefs.getString("dm_registration", "");

        return registrationId;

    }

 

    public static long getLastRegistrationChange(Context context) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        return prefs.getLong(LAST_REGISTRATION_CHANGE, 0);

    }

 

    static long getBackoff(Context context) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        return prefs.getLong(BACKOFF, DEFAULT_BACKOFF);

    }

 

    static void setBackoff(Context context, long backoff) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        Editor editor = prefs.edit();

        editor.putLong(BACKOFF, backoff);

        editor.commit();

 

    }

 

    // package

    static void clearRegistrationId(Context context) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        Editor editor = prefs.edit();

        editor.putString("dm_registration", "");

        editor.putLong(LAST_REGISTRATION_CHANGE, System.currentTimeMillis());

        editor.commit();

 

    }

 

    // package

    static void setRegistrationId(Context context, String registrationId) {

        final SharedPreferences prefs = context.getSharedPreferences(

                PREFERENCE, Context.MODE_PRIVATE);

        Editor editor = prefs.edit();

        editor.putString("dm_registration", registrationId);

        editor.commit();

 

    }

}

代码中已添加了部分中文注释,可以先大概了解下,等整个工程建立完了在一起解释。

然后创建我们自己的包com.ichliebephone.c2dm,包含两个类,一个是工程的入口AndroidC2DMDemo:

package com.ichliebephone.c2dm;

 

import com.google.android.c2dm.C2DMessaging;

import android.app.Activity;

import android.os.Bundle;

import android.util.Log;

 

public class AndroidC2DMDemo extends Activity {

    /** Called when the activity is first created. */

    private static final String TAG = "AndroidC2DMDemo";

    public static final String SENDER_ID = "android.c2dm.demo@gmail.com"; // 使用C2DM服务的用户账户

    public static final String MESSAGE_KEY_ONE = "msg"; // 和服务器商量好的接收消息的键值key

 

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

 

        Log.v(TAG, "Start");

        // 向C2DM服务器注册

        C2DMessaging.register(this, SENDER_ID);

    }

}

很简单,就是开始向C2DM服务器进行注册。

另一个类为C2DMBaseReceiver的子类C2DMReceiver:

package com.ichliebephone.c2dm;

 

import java.io.IOException;

import android.app.Notification;

import android.app.NotificationManager;

import android.app.PendingIntent;

import android.content.Context;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

 

import com.google.android.c2dm.C2DMBaseReceiver;

 

//接收C2DM服务器Push的消息,包括注册返回的registration_id消息,推送的数据消息等

public class C2DMReceiver extends C2DMBaseReceiver {

 

    private static final String TAG = "C2DMReceiver";

 

    //

    public C2DMReceiver() {

        super(AndroidC2DMDemo.SENDER_ID);

    }

 

    public C2DMReceiver(String senderId) {

        super(senderId);

        // TODO Auto-generated constructor stub

    }

 

    // 接收到Push消息的回调函数

    @Override

    protected void onMessage(Context context, Intent intent) {

        // TODO Auto-generated method stub

        Log.v(TAG, "C2DMReceiver message");

        Bundle extras = intent.getExtras();

        if (extras != null) {

            String msg = (String) extras.get(AndroidC2DMDemo.MESSAGE_KEY_ONE);

            Log.v(TAG, "The received msg = " + msg);

            // 在标题栏上显示通知

            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

            Notification notification = new Notification(R.drawable.icon, msg,

                    System.currentTimeMillis());

            PendingIntent contentIntent = PendingIntent.getActivity(this, 0,

                    new Intent(this, AndroidC2DMDemo.class), 0);

            notification.setLatestEventInfo(this, getString(R.string.app_name),

                    msg, contentIntent);

            notificationManager.notify(0, notification);

 

        }

    }

 

    @Override

    public void onError(Context context, String errorId) {

        // TODO Auto-generated method stub

        Log.v(TAG, "C2DMReceiver error");

    }

 

    @Override

    public void onRegistered(Context context, String registrationId)

            throws IOException {

        // TODO Auto-generated method stub

        super.onRegistered(context, registrationId);

        Log.v(TAG, "C2DMReceiver Register");

    }

 

    @Override

    public void onUnregistered(Context context) {

        // TODO Auto-generated method stub

        super.onUnregistered(context);

        Log.v(TAG, "C2DMReceiver UnRegister");

    }

}

在这个类中我们主要在接收到Push的回调函数onMessage中对消息进行了接收,并且使用Notification的方式显示在状态栏上。

我们完整的工程目录是这样的:

图片 9
图4 工程目录

最后我们还要在AndroidManifest.xml中增加对应的权限等内容:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=""

    package="com.ichliebephone.c2dm" android:versionCode="1"

    android:versionName="1.0">

    <uses-sdk android:minSdkVersion="8" />

 

    <!--Only this application can receive the message and registration result -->

    <!-- 设置一个权限,使只有这个应用才能接收到对应Push的消息及注册时返回的结果 -->

    <permission android:name="com.ichliebephone.c2dm.permission.C2D_MESSAGE"

        android:protectionLevel="signature"></permission>

    <uses-permission android:name="com.ichliebephone.c2dm.permission.C2D_MESSAGE" />

    <!-- This application has the permission to register and receive c2dm message -->

    <!-- 设置注册和接收C2DM Push消息的权限 -->

    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <!-- Send and registration id to the server -->

    <!-- 设置联网权限,在把registration_id发送给服务器的时候要用 -->

    <uses-permission android:name="android.permission.INTERNET" />

    <!-- App must have this permission to use the library -->

    <!-- 其他和获取手机中用户账户相关的权限 -->

    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <uses-permission android:name="android.permission.GET_ACCOUNTS" />

    <uses-permission android:name="android.permission.USE_CREDENTIALS" />

 

    <application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".AndroidC2DMDemo" android:label="@string/app_name">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

 

        <!-- In order to use the c2dm library, an application must declare a class 

            with the name C2DMReceiver, in its own package, extending com.google.android.c2dm.C2DMBaseReceiver 

            It must also include this section in the manifest. -->

        <!-- 为了使用c2dm包com.google.android.c2dm及其对应的3个类,我们需要声明一个 继承com.google.android.c2dm.C2DMBaseReceiver类的子类C2DMReceiver, 

            并且要在这声明下 -->

        <service android:name=".C2DMReceiver" />

 

        <!-- Only google service can send data messages for the app. If permission 

            is not set - any other app can generate it -->

        <!-- 谷歌的C2DM服务只为这个程序发送数据,声明对应的权限 -->

        <receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver"

            android:permission="com.google.android.c2dm.permission.SEND">

            <!-- Receive the actual message -->

            <!-- 可以接收实际的Push数据 -->

            <intent-filter>

                <action android:name="com.google.android.c2dm.intent.RECEIVE" />

                <category android:name="com.ichliebephone.c2dm" />

            </intent-filter>

            <!-- Receive the registration id -->

            <!-- 可以接收注册后返回的registration_id -->

            <intent-filter>

                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

                <category android:name="com.ichliebephone.c2dm" />

            </intent-filter>

        </receiver>

    </application>

</manifest>

因为C2DM功能只有2.2及以上的Android系统才支持,因此创建一个2.2及以上的AVD,然后在”设置->账户与同步”里还要设置好Google Account,如下图所示:

图片 10
图5 设置Android设备中的Google账户

然后就可以运行程序了,我们会在DDMS输出中看到获得的registration_id:

图片 11
图6 获得的registration_id

如果第一次运行没有出现,试着再运行一次。

有了registration_id,我们的服务器端就可以向C2DM端发送需要Push的数据了,这里进行简单化处理下,在Ubuntu下直接使用curl命令来模拟服务器功能向C2DM发送数据。

我们先来获取C2DM的ClientLogin权限Auth,在Ubuntu终端下输入:

lingaohe@lingaohe-laptop:~$ curl -d "accountType=HOSTED_OR_GOOGLE&Email=android.c2dm.demo@gmail.com&Passwd=androidc2dmdemo&service=ac2dm&source=bupt-c2dmdemo-1.0"

这个表示以POST的方式向

如果你的邮箱已在C2DM网页上注册,并且密码没有错误的话就会返回需要的Auth内容:

SID=DQAAAKYAAADcTtHbBBNcZJEOfkfVRycD_ZOIidwsQ3UwIY7cSrYWaY6uhlfo0l9gRPB-mQxP4K2T5tWiG--vWVmSTeq5p8SPwgnsYvfzj7bkNiPPIy4xRimVVfBmAHnZgLohw7gHMKi5DS6kK-Ut5tNzdTkI0I2tUDF0ryQ7MnPpI6Sj-gUCyBXmvKatHHDnNTTV78XdGIx7FYej1DyqGsPsYo3bCstHgltjv3cd2Hs7D4yrpUWHZw

LSID=DQAAAKgAAABCpaoUE4XvxM24Cofntw1IUGx5fKxX-m7aqTL0zhunP0OjzJ2sn9ywmPa1BMZ2cF2IchuxHFLVzaSQfydAmiHZJGXLgaUorpIN6yz1e0VFWKmS6j4wGjZOos3QoJ9rkha0jKbOiHfBesADjxk-qjJ24TJ0RL-xkZHQyzS69YlA1KyzqIKjAMCzgqaDfCwhqxylJzizJksO2h8xpAFXZ38d_grm8XYZtzejiCiAMAR65A

Auth=DQAAAKoAAACRF4pgYULnXULoWgbwfdqmMiRhfZYa1l-LW_rwGD7cofov4L4c2bVrtCOXbEbkju_hhqdAonpMkrb5icptt28fU8c-s-u1y2MXNYDxPIdQzfA2t6oI3NTmyj35MpsR1NKL4TN7ZVEn6z9NueuiKAqLHukZYh1YMGkGC8M6rVvA7AWPW36064XCQED7KLVNp_pGT00lrni7UdZKZWEy0FT-EVR-OxDyHWw6C-5Kmfkisw

返回的内容包括SID,LSID和Auth三个部分,其中Auth是我们需要的内容。

有了Auth和registration_id值后,我们就可以继续用curl命令模拟我们自己服务器的功能向C2DM发送要推送的数据:

lingaohe@lingaohe-laptop:~$ curl -H "Authorization:GoogleLogin auth=DQAAAKoAAACRF4pgYULnXULoWgbwfdqmMiRhfZYa1l-LW_rwGD7cofov4L4c2bVrtCOXbEbkju_hhqdAonpMkrb5icptt28fU8c-s-u1y2MXNYDxPIdQzfA2t6oI3NTmyj35MpsR1NKL4TN7ZVEn6z9NueuiKAqLHukZYh1YMGkGC8M6rVvA7AWPW36064XCQED7KLVNp_pGT00lrni7UdZKZWEy0FT-EVR-OxDyHWw6C-5Kmfkisw" -d "registration_id=APA91bGUBoSvt3G5Ny9t0IGLmIKAKYX6G6VHwSQHh3tP2fqcaQ0N4GPdKh5B3RDUHFCFF06YwT8ifOP_cOy5BAWyCLHL8d8NpuIW9AqXt9h2JSBVF2MitZA&collapse_key=1&data.msg=ichliebejiajia"

其中发送的数据部分为data.msg=ichliebejiajia,表示发送的数据内容为ichliebejiajia,键值为msg,键值得和Android终端上的程序统一好,以便终端上可以获取。如果发送成功,会返回一个id值,比如:

id=0:1308623423080544%6c5c15c200000031

lingaohe@lingaohe-laptop:~$

这时我们的服务器就已经把数据发送给C2DM服务器了,Android设备上一会就能接收到C2DM服务器Push的数据。

在我们的例子中我们可以看到DDMS中打印出的消息:

图片 12
图7 获取到的Push数据

同时Android模拟器的状态栏上会有对应的通知显示:

图片 13
图8 Android模拟器接收到的Push数据

这样我们就快速实现了下Android的C2DM框架的Push功能。进一步的具体解释说明及服务器端的代码处理我们以后再学习。

本文由奇幻城娱乐网址发布于母婴,转载请注明出处:云端推送,实现Android消息推送

关键词: