1 GCM简介

     GCM(Google Cloud Message for Android)是Google发布的Android服务器推送(push)技术。之前的C2DM(Android Cloud to Device Messaging)已与2012年6月26日被正式弃用,使用GCM,需要申请开通Google apis,Google apis包括了所有Google服务的api,比如Google Map、Google+、Analytics、YouTube等等,申请地址为: Google API 网站。

    Google Cloud Messaging for Android (GCM)是一个能够帮助开发者从服务器端发送数据到运行在Android手机上的程序的服务。这个服务提供了一个简单,轻量级的机制使得服务器端可以告诉移动端的程序与服务器端建立直接的联系,来获取更新的程序或者用户的数据。C2DM服务可以处理所有的消息队列的问题并且可以把消息发送到目标机器上运行的目标程序。

2 GCM 特点

1  它允许第三方的程序服务端发送消息到他们的安卓设备。

2  GCM不能保证消息的发送和消息的顺序。

3  手机端的程序不需要一直运行来接收消息。系统会通过Intent  broadcast来唤醒程序当有新的消息到来时。当然程序需要设置适当的broadcast  receiver和permission。

4  它不提供任何的用户界面或者其他的东西来处理消息。C2DM只是简单的把收到的原始消息传递给程序。这个程序提供了处理这个消息的方法。比如,这个程序可能抛出一个通知,显示一个自定义的界面或者只是同步数据。

5  GCM要求手机必须运行Android2.2或者更高版本并且要有Google Play Store ,或者运行具有谷歌api 的Android 2.2虚拟机。但是,你不仅限于通过Google Play Store部署你的程序。

6  它使用一个现有的连接用于谷歌服务。对前置3.0设备,这要求用户在他们的移动设备设置他们的谷歌账户。Android 4.0.4或更高对于谷歌帐户是不要求的。

3 GCM在客户端的使用

GCM运行时需要三个参数:

Project Number 从api控制台获得project number,Project Number用在注册阶段去识别被允许发送消息到手机的android程序。(用在运用程序的客户端)

Application ID: 也称为API key,注册了用来接收消息的程序。 这个程序是通过manifest的包名来识别的。 这样确保消息会发送到正确的程序。(用在运用程序的服务端)

Registration ID:这个ID是C2DM服务器分发的,用来允许程序接收消息。 当程序有了registration ID, 就把这个ID发送到第三方程序服务器, 第三方服务器用ID来识别每一个注册了来接收消息的手机。换句话说,registration ID是和运行在某个手机上的摸个程序绑定的。

条件:

 Google User Account:如果GCM要工作,手机就至少有一个已经登录的google账户,如果设备运行Android版本GCM低于4.0.4,则不需要。

GCM使用所要添加的权限:

1.  需要Android2.2或更高版本,所以如果你的程序不依赖GCM就无法正常工作,那么请在AndroidManifest文件中添加以下内容,“xx”处替换为最新的目标SDK版本号:

<uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="xx"/>                                                           

2.添加联网权限  android.permission.INTERNET

3. 设备版本低于4.0.4时需要添加如下权限,需要谷歌帐号   android.permission.GET_ACCOUNTS permission

4. 可以保证处理器在睡觉的时候得到消息    android.permission.WAKE_LOCK permission

5.  声明并使用一个自定义的权限以此来确保只有这个程序可以接收你的GCM消息:

<permissionandroid:name="my_app_package.permission.C2D_MESSAGE"

android:protectionLevel="signature"/>

<uses-permissionandroid:name="my_app_package.permission.C2D_MESSAGE"/>

 这个权限必须称作:my_app_package.permission.C2D_MESSAG(程序包名.permission.C2D_MESSAG,程序包名就是在manifest文件中定义包名),不然将不能正常运行。

6.  添加权限接收GCM消息:

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

7.  添加以下广播接收器:

<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="my_app_package"/>
    </intent-filter>
</receiver>

 这个Broadcast receiver负责处理2个从GCM发来的Intent(com.google.android.c2dm.intent.RECEIVE和com.google.android.c2dm.intent.REGISTRATION),并且要在manifest文件中定义(而非通过编码实现)。因此,这些Intent甚至可以在程序未运行的情况下被接收到。

   通过设置com.google.android.c2dm.permission.SEND权限,可以确保这些Intent只能通过GCM系统框架发送到这个receiver(普通程序是没有权限发出这些Intent的)。

   注意在category标签里的android:name必须替换成你程序的包名(如果程序是针对16或更高的minSdkVersion的平台那么就不需要有category这个标签了)。

  8. 添加如下Intent权限:

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

    注意:在下一步中,这个Intent服务会被GCMBroadcastReceiver(由GCM库提供)调用。它必须称作my_app_package.GCMIntentService,除非你用重写了GCMBroadcastRecevier方法的子类来作为此服务的名字。

  GCM关键代码:

 第一步:实现my_app_package.GCMIntentService类(次Service不是Android中的Service,而是GCM中的一个机制)

     继承GCMBaseIntentService类,并实现如下几个方法:

  • onRegistered(Context context, String regId): 收到注册Intent后此方法会被调用,GCM分配的注册ID会做为参数传递到设备/应用程序对。通常,你应该发送regid到你的服务器,这样服务器就可以根据这个regid发消息到设备上。
  • onUnregistered(Context context, String regId): 当设备从GCM注销时会被调用。通常你应该发送regid到服务器,这样就可以注销这个设备了。
  • onMessage(Context context, Intent intent): 当你的服务器发送了一个消息到GCM后会被调用,并且GCM会把这个消息传送到相应的设备。如果这个消息包含有效负载数据,它们的内容会作为Intent的extras被传送。
  • onError(Context context, String errorId): 当设备试图注册或注销时,但是GCM返回错误时此方法会被调用。通常此方法就是分析错误并修复问题而不会做别的事情。
  • onRecoverableError(Context context, String errorId): 当设备试图注册或注销时,但是GCM服务器无效时。GCM库会使用应急方案重试操作,除非这个方式被重写并返回false。这个方法是可选的并且只有当你想显示信息给用户或想取消重试操作的时候才会被重写。

 

注意:上面的方法运行在Intent服务的线程里,因此可以自由访问网络而不会阻塞UI线程。

 

 

 

第二步:在程序activity中的代码

在onCreate()方法里面添加如下代码:

GCMRegistrar.checkDevice(this);
                   GCMRegistrar.checkManifest(this);
                   regid=GCMRegistrar.getRegistrationId(this);
              if(regid.equals("")){
                    GCMRegistrar.register(this, GlobalCast.GCM_SENDER_ID);
              }
            else{
                  try {   
                //通常这里要向自己的服务器发送注册的RegistrationId
      UARWebService mUarWebService=new UARWebService(Activity.this,mVolley.requestQueue);
       mUarWebService.sendPushInfo(String.valueOf(Constants.customer.customerId), regid);
                     } catch (Exception e) {
                           e.printStackTrace();
                     }                   
           }

checkDevice()方法用来验证设备是否支持GCM,如果不支持会抛出异常(例如,模拟器就不包含Google APIs)

checkManifest()方法来验证程序的manifest包含了在开始编写Android程序中所有符合要求的描述(这个方法只有你在开发程序的时候需要;一旦这个程序准备发布的时候,你就可以把它移除掉)。

GCMRegsistrar.register()通过传送注册GCM时得到的SENDER_ID来注册设备了。但是由于GCMRegistrar单例保持跟踪所有收到的注册Intent的注册ID,所以可以先调用GCMRegistrar.getRegistrationId()方法检查此设备是否已经注册。

4 GCM在服务端的简单使用

关键代码如下:

import com.google.android.gcm.server.*;
Sender sender = new Sender(myApiKey);
Message message = new Message.Builder().build();
MulticastResult result = sender.send(message, devices, 5);

上面的代码段实现了如下工作:

  • 用你项目的API key创建一个Sender对象。
  • 用获得的注册ID来创建一个消息(消息的构建者也要有方法来设置全部的消息参数,例如collapse key和有效负载数据)。
  • 发送这个消息(如果GCM服务器无效的话,有5次重发机会),并保存响应给result。
  • 现在就需要解析响应结果并对如下情况采取适当的措施:
  • 如果消息被创建了,但是结果返回了一个被认可的注册ID,那么需要用这个认可的ID替换当前的注册ID。
  • 如果返回的错误是NotRegistered,那么需要移除这个注册ID,因为那个设备没有安装此程序。