Android Cloud to Device Messaging Framework(二)

Writing Android Application that use C2DM

想要写一个使用C2DM的程序,你必须有一个程序服务器端能够执行 Role of the Third-Party Application Server所描述的任务。这一节描述了你创建一个使用C2DM客户端的步骤。

请记住C2DM是没有用户界面的。怎么在程序里处理消息取决于你。

写个程序客户端有两个主要步骤:

1.    创建一个manifest文件。这个文件包含程序使用C2DM需要使用的权限。

2.    java代码。要使用C2DM,程序要包括:

A. 开始和停止注册服务的代码。

B. Receivers for com.google.android.c2dm.intent.C2D_MESSAGE com.google.android.c2dm.intent.REGISTRATION

Creating the Manifest

每一个程序在根目录下都有一个AndroidManifest.xml文件。这个文件提供程序的必要信息给Android系统,这些信息是系统在运行任何程序代码之前必须要有的。要使用C2DM,这个文件必须包含:

1.    com.google.android.c2dm.permission.RECEIVE。程序拥有注册和接受消息的权限。

2.    android.permission.INTERNET。程序拥有联网的权限。

3.    applicationPackage+”.permission.C2D_MESSAGE”防止其他程序注册和接受这个程序的消息。

4.    Receivers for com.google.android.c2dm.intent.RECEIVEcom.google.android.c2dm.intent.REGISTRATION.category设置成applicationPackagereceiver需要com.google.android.c2dm.SEND权限,这样C2DM就可以发送消息给它。Registration和消息接收都是通过Intents来实现的

5.    如果C2DM对于你的程序是一个至关重要的功能,就一定要在AndroidManifest.xml里设置andorid:minSdkVersion=”8”。这样就确保了程序不会装在一些程序不能正常运行的手机上。

 

Received C2D_MESSAGE Intents包含第三方服务器发送过来的键值对。一个特别的keycollapse_key。这是发送者设置的允许离线的设备在上线时处理消息。

 

下面是一个支持C2DMmanifest的例子:

<manifest package="com.example.myapp" ...>

<!—只有这个程序能注册和接受消息 -->
<permission android:name="yourpackagename.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="yourpackagename.permission.C2D_MESSAGE" />

<!—这个程序有注册和接收消息的权限 -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<!—发送registration id到服务器需要的权限 -->
<uses-permission android:name="android.permission.INTERNET" />

<!—只有C2DM服务器可以发送消息给程序. 如果下面的权限不设置,其他的程序也能发送 -->
<receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND">
    <!—接收消息 -->
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="yourpackagename" />
    </intent-filter>
    <!—接收registration id -->
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="yourpackagename " />
    </intent-filter>
</receiver>

Registering for C2DM

Android程序在接收任何消息前需要向C2DM服务器注册。如果要注册,需要发送一个intent(com.google.android.c2dm.intent.REGISTER),包含2个参数:

1.    sender:是一个授权发送消息到程序的ID,通常是程序开发者设置的一个gmail地址。

2.    appapplication’s ID.通过PendingIntent设置来允许registration service提取程序信息。

比如:

 Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER");
 registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate
 registrationIntent.putExtra("sender", emailOfSender);
 startService(registrationIntent); 

直到程序把registration ID发送到第三方程序服务器,注册才结束。第三方程序服务器使用这个registration ID发送消息给目标机器上的目标程序。

Unregistering from C2DM

 Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER");
 unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
 startService(unregIntent); 

Handling Registration Results

AndroidManifest.xml里,定义了一个receivercom.google.android.c2dm.intent.REGISTRATION。同样定义了一个receivercom.google.android.c2dm.intent.RECEIVEregistration和接受消息都是通过Intents实现的。

REGISTRATION的主要作用是允许程序接收registration ID。这个Intent可以在任何时候发送。Google可能定期刷新receiver ID。一个程序收到Intent包含registration_id 这个参数,必须确保第三方程序服务器收到registration ID。可以通过保存registration ID并发送到服务器来实现。如果网络断了或者有错误,程序应该尝试重新发送registration ID当网络连接上的时候。程序应该追踪registration的状态并且尝试重新注册当处理没完成的时候。

当注册没有完成的时候,REGISTRATION通常产生错误。如果发生了错误,程序应该稍后重试。当程序解除注册的时候,会发送包含unregisteered作为参数的REGISTRATION Intent

下面是REGISTRATION Intent可能的error codes

Error Code

Description

SERVICE_NOT_AVAILABLE

手机不能读取响应或者有500/503错误.程序应该使用指数退避然后重试。

ACCOUNT_MISSING

手机上没有登录google账户. 程序应该要求用户打开账户控制并增加一个账户。

AUTHENTICATION_FAILED

错误的密码,程序应该让用户输入正确的密码,并在稍后手动重试。

TOO_MANY_REGISTRATIONS

用户有太多的注册程序. 程序应该告诉用户卸载一部分注册程序。然后手动重试。

INVALID_SENDER

Sender account不能被识别。

PHONE_REGISTRATION_ERROR

这个手机现在不支持C2DM

程序收到一个REGISTRATION Intent 广播当第三方程序服务器尝试发送消息给它的时候。但是registration IDs不存在的原因有以下几种:

1.    程序第一次运行,还没有registration ID

2.    程序解除注册。

3.    C2DM服务器端定时刷新了registration IDs

程序必须准备好去应对这几种情况,比如:

 public void onReceive(Context context, Intent intent) {
     if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION")) { 
 //注册相关
         handleRegistration(context, intent);
     } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE")) { 
 //消息相关
         handleMessage(context, intent);
      }
  }
 
private void handleRegistration(Context context, Intent intent) {
     String registration = intent.getStringExtra("registration_id"); 
     if (intent.getStringExtra("error") != null) {
         // 注册失败。稍后重试
     } else if (intent.getStringExtra("unregistered") != null) {
         // 解除注册成功。授权的服务器发送的新消息将会被拒绝。    
  } else if (registration != null) {
        // 发送 registration ID 到发送消息的第三方程序服务器。
        //应该开启一个新的线程去发送 registration ID到此,注册就完了。 
     }
} 

Handling Received Data

C2DM服务器收到从第三方程序服务器发送过来的消息时,C2DM服务器从消息中提取出键值对然后以com.google.android.c2dm.intent.RECEIVE Intent作为载体,把键值对发送到程序。程序根据key从消息中提取数据并处理数据。

比如:

 protected void onReceive(Context context, Intent intent) {
     String accountName = intent.getExtras().getString(Config.C2DM_ACCOUNT_EXTRA);
     String message = intent.getExtras().getString(Config.C2DM_MESSAGE_EXTRA);
     if (Config.C2DM_MESSAGE_SYNC.equals(message)) {
         if (accountName != null) {
             if (Log.isLoggable(TAG, Log.DEBUG)) {
                 Log.d(TAG, "Messaging request received for account " + accountName);
             }
             
             ContentResolver.requestSync(
                 new Account(accountName, SyncAdapter.GOOGLE_ACCOUNT_TYPE),
                 JumpNoteContract.AUTHORITY, new Bundle());
         }
     }
} 

你可能感兴趣的:(framework)