Android C2DM 实现消息推送

来源:互联网 发布:cbox网络官网下载 编辑:程序博客网 时间:2024/05/22 13:05


    博客分类:  
  • Android

AndroidC2DMDemo

 

com.google.android.c2dm

 

C2DMBroadcastReceiver

Java代码  收藏代码
  1. /* 
  2.  */  
  3. package com.google.android.c2dm;  
  4.   
  5. import android.app.Activity;  
  6. import android.content.BroadcastReceiver;  
  7. import android.content.Context;  
  8. import android.content.Intent;  
  9.   
  10. /** 
  11.  * Helper class to handle BroadcastReciver behavior. 
  12.  * - can only run for a limited amount of time - it must start a real service  
  13.  * for longer activity 
  14.  * - must get the power lock, must make sure it's released when all done. 
  15.  *  
  16.  */  
  17. public class C2DMBroadcastReceiver extends BroadcastReceiver {  
  18.       
  19.     @Override  
  20.     public final void onReceive(Context context, Intent intent) {  
  21.         // To keep things in one place.  
  22.         C2DMBaseReceiver.runIntentInService(context, intent);  
  23.         setResult(Activity.RESULT_OK, null /* data */null /* extra */);          
  24.     }  
  25. }  

 

C2DMBaseReceiver

Java代码  收藏代码
  1. /* 
  2.  * Copyright 2010 Google Inc. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *   http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.google.android.c2dm;  
  18.   
  19. import java.io.IOException;  
  20.   
  21. import android.app.AlarmManager;  
  22. import android.app.IntentService;  
  23. import android.app.PendingIntent;  
  24. import android.content.Context;  
  25. import android.content.Intent;  
  26. import android.os.PowerManager;  
  27. import android.util.Log;  
  28.   
  29. /** 
  30.  * Base class for C2D message receiver. Includes constants for the 
  31.  * strings used in the protocol. 
  32.  */  
  33. public abstract class C2DMBaseReceiver extends IntentService {  
  34.     private static final String C2DM_RETRY = "com.google.android.c2dm.intent.RETRY";  
  35.   
  36.     public static final String REGISTRATION_CALLBACK_INTENT = "com.google.android.c2dm.intent.REGISTRATION";  
  37.     private static final String C2DM_INTENT = "com.google.android.c2dm.intent.RECEIVE";  
  38.   
  39.     // Logging tag  
  40.     private static final String TAG = "C2DM";  
  41.   
  42.     // Extras in the registration callback intents.  
  43.     public static final String EXTRA_UNREGISTERED = "unregistered";  
  44.   
  45.     public static final String EXTRA_ERROR = "error";  
  46.   
  47.     public static final String EXTRA_REGISTRATION_ID = "registration_id";  
  48.   
  49.     public static final String ERR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE";  
  50.     public static final String ERR_ACCOUNT_MISSING = "ACCOUNT_MISSING";  
  51.     public static final String ERR_AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED";  
  52.     public static final String ERR_TOO_MANY_REGISTRATIONS = "TOO_MANY_REGISTRATIONS";  
  53.     public static final String ERR_INVALID_PARAMETERS = "INVALID_PARAMETERS";  
  54.     public static final String ERR_INVALID_SENDER = "INVALID_SENDER";  
  55.     public static final String ERR_PHONE_REGISTRATION_ERROR = "PHONE_REGISTRATION_ERROR";  
  56.       
  57.     // wakelock  
  58.     private static final String WAKELOCK_KEY = "C2DM_LIB";  
  59.   
  60.     private static PowerManager.WakeLock mWakeLock;  
  61.     private final String senderId;  
  62.   
  63.     /** 
  64.      * The C2DMReceiver class must create a no-arg constructor and pass the  
  65.      * sender id to be used for registration. 
  66.      */  
  67.     public C2DMBaseReceiver(String senderId) {  
  68.         // senderId is used as base name for threads, etc.  
  69.         super(senderId);  
  70.         this.senderId = senderId;  
  71.     }  
  72.       
  73.     /** 
  74.      * Called when a cloud message has been received. 
  75.      */  
  76.     protected abstract void onMessage(Context context, Intent intent);  
  77.   
  78.     /** 
  79.      * Called on registration error. Override to provide better 
  80.      * error messages. 
  81.      *   
  82.      * This is called in the context of a Service - no dialog or UI. 
  83.      */  
  84.     public abstract void onError(Context context, String errorId);  
  85.   
  86.     /** 
  87.      * Called when a registration token has been received. 
  88.      */  
  89.     public void onRegistered(Context context, String registrationId) throws IOException {  
  90.         // registrationId will also be saved  
  91.     }  
  92.   
  93.     /** 
  94.      * Called when the device has been unregistered. 
  95.      */  
  96.     public void onUnregistered(Context context) {  
  97.     }  
  98.   
  99.       
  100.     @Override  
  101.     public final void onHandleIntent(Intent intent) {  
  102.         try {  
  103.             Context context = getApplicationContext();  
  104.             if (intent.getAction().equals(REGISTRATION_CALLBACK_INTENT)) {  
  105.                 handleRegistration(context, intent);  
  106.             } else if (intent.getAction().equals(C2DM_INTENT)) {  
  107.                 onMessage(context, intent);  
  108.             } else if (intent.getAction().equals(C2DM_RETRY)) {  
  109.                 C2DMessaging.register(context, senderId);  
  110.             }  
  111.         } finally {  
  112.             //  Release the power lock, so phone can get back to sleep.  
  113.             // The lock is reference counted by default, so multiple   
  114.             // messages are ok.  
  115.               
  116.             // If the onMessage() needs to spawn a thread or do something else,  
  117.             // it should use it's own lock.  
  118.             mWakeLock.release();  
  119.         }  
  120.     }  
  121.   
  122.       
  123.     /** 
  124.      * Called from the broadcast receiver.  
  125.      * Will process the received intent, call handleMessage(), registered(), etc. 
  126.      * in background threads, with a wake lock, while keeping the service  
  127.      * alive.  
  128.      */  
  129.     static void runIntentInService(Context context, Intent intent) {  
  130.         if (mWakeLock == null) {  
  131.             // This is called from BroadcastReceiver, there is no init.  
  132.             PowerManager pm =   
  133.                 (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
  134.             mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,   
  135.                     WAKELOCK_KEY);  
  136.         }  
  137.         mWakeLock.acquire();  
  138.          
  139.         // Use a naming convention, similar with how permissions and intents are   
  140.         // used. Alternatives are introspection or an ugly use of statics.   
  141.         String receiver = context.getPackageName() + ".C2DMReceiver";  
  142.         intent.setClassName(context, receiver);  
  143.           
  144.         context.startService(intent);  
  145.   
  146.     }  
  147.       
  148.       
  149.     private void handleRegistration(final Context context, Intent intent) {  
  150.         final String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);  
  151.         String error = intent.getStringExtra(EXTRA_ERROR);  
  152.         String removed = intent.getStringExtra(EXTRA_UNREGISTERED);  
  153.   
  154.         if (Log.isLoggable(TAG, Log.DEBUG)) {  
  155.             Log.d(TAG, "dmControl: registrationId = " + registrationId +  
  156.                 ", error = " + error + ", removed = " + removed);  
  157.         }  
  158.   
  159.         if (removed != null) {  
  160.             // Remember we are unregistered  
  161.             C2DMessaging.clearRegistrationId(context);  
  162.             onUnregistered(context);  
  163.             return;  
  164.         } else if (error != null) {  
  165.             // we are not registered, can try again  
  166.             C2DMessaging.clearRegistrationId(context);  
  167.             // Registration failed  
  168.             Log.e(TAG, "Registration error " + error);  
  169.             onError(context, error);  
  170.             if ("SERVICE_NOT_AVAILABLE".equals(error)) {  
  171.                 long backoffTimeMs = C2DMessaging.getBackoff(context);  
  172.                   
  173.                 Log.d(TAG, "Scheduling registration retry, backoff = " + backoffTimeMs);  
  174.                 Intent retryIntent = new Intent(C2DM_RETRY);  
  175.                 PendingIntent retryPIntent = PendingIntent.getBroadcast(context,   
  176.                         0 /*requestCode*/, retryIntent, 0 /*flags*/);  
  177.                   
  178.                 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);  
  179.                 am.set(AlarmManager.ELAPSED_REALTIME,  
  180.                         backoffTimeMs, retryPIntent);  
  181.   
  182.                 // Next retry should wait longer.  
  183.                 backoffTimeMs *= 2;  
  184.                 C2DMessaging.setBackoff(context, backoffTimeMs);  
  185.             }   
  186.         } else {  
  187.             try {  
  188.                 onRegistered(context, registrationId);  
  189.                 C2DMessaging.setRegistrationId(context, registrationId);  
  190.             } catch (IOException ex) {  
  191.                 Log.e(TAG, "Registration error " + ex.getMessage());  
  192.             }  
  193.         }  
  194.     }  
  195. }  

 

C2DMessaging

Java代码  收藏代码
  1. /* 
  2.  * Copyright 2010 Google Inc. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *   http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package com.google.android.c2dm;  
  18.   
  19. import android.app.PendingIntent;  
  20. import android.content.Context;  
  21. import android.content.Intent;  
  22. import android.content.SharedPreferences;  
  23. import android.content.SharedPreferences.Editor;  
  24.   
  25. /** 
  26.  * Utilities for device registration. 
  27.  * 
  28.  * Will keep track of the registration token in a private preference. 
  29.  */  
  30. public class C2DMessaging {  
  31.     public static final String EXTRA_SENDER = "sender";  
  32.     public static final String EXTRA_APPLICATION_PENDING_INTENT = "app";  
  33.     public static final String REQUEST_UNREGISTRATION_INTENT = "com.google.android.c2dm.intent.UNREGISTER";  
  34.     public static final String REQUEST_REGISTRATION_INTENT = "com.google.android.c2dm.intent.REGISTER";  
  35.     public static final String LAST_REGISTRATION_CHANGE = "last_registration_change";  
  36.     public static final String BACKOFF = "backoff";  
  37.     public static final String GSF_PACKAGE = "com.google.android.gsf";  
  38.   
  39.   
  40.     // package  
  41.     static final String PREFERENCE = "com.google.android.c2dm";  
  42.       
  43.     private static final long DEFAULT_BACKOFF = 30000;  
  44.   
  45.     /** 
  46.      * Initiate c2d messaging registration for the current application 
  47.      */  
  48.     public static void register(Context context,  
  49.             String senderId) {  
  50.         Intent registrationIntent = new Intent(REQUEST_REGISTRATION_INTENT);  
  51.         registrationIntent.setPackage(GSF_PACKAGE);  
  52.         registrationIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT,  
  53.                 PendingIntent.getBroadcast(context, 0new Intent(), 0));  
  54.         registrationIntent.putExtra(EXTRA_SENDER, senderId);  
  55.         context.startService(registrationIntent);  
  56.         // TODO: if intent not found, notification on need to have GSF  
  57.     }  
  58.   
  59.     /** 
  60.      * Unregister the application. New messages will be blocked by server. 
  61.      */  
  62.     public static void unregister(Context context) {  
  63.         Intent regIntent = new Intent(REQUEST_UNREGISTRATION_INTENT);  
  64.         regIntent.setPackage(GSF_PACKAGE);  
  65.         regIntent.putExtra(EXTRA_APPLICATION_PENDING_INTENT, PendingIntent.getBroadcast(context,  
  66.                 0new Intent(), 0));  
  67.         context.startService(regIntent);  
  68.     }  
  69.   
  70.     /** 
  71.      * Return the current registration id. 
  72.      * 
  73.      * If result is empty, the registration has failed. 
  74.      * 
  75.      * @return registration id, or empty string if the registration is not complete. 
  76.      */  
  77.     public static String getRegistrationId(Context context) {  
  78.         final SharedPreferences prefs = context.getSharedPreferences(  
  79.                 PREFERENCE,  
  80.                 Context.MODE_PRIVATE);  
  81.         String registrationId = prefs.getString("dm_registration""");  
  82.         return registrationId;  
  83.     }  
  84.   
  85.     public static long getLastRegistrationChange(Context context) {  
  86.         final SharedPreferences prefs = context.getSharedPreferences(  
  87.                 PREFERENCE,  
  88.                 Context.MODE_PRIVATE);  
  89.         return prefs.getLong(LAST_REGISTRATION_CHANGE, 0);  
  90.     }  
  91.       
  92.     static long getBackoff(Context context) {  
  93.         final SharedPreferences prefs = context.getSharedPreferences(  
  94.                 PREFERENCE,  
  95.                 Context.MODE_PRIVATE);  
  96.         return prefs.getLong(BACKOFF, DEFAULT_BACKOFF);  
  97.     }  
  98.       
  99.     static void setBackoff(Context context, long backoff) {  
  100.         final SharedPreferences prefs = context.getSharedPreferences(  
  101.                 PREFERENCE,  
  102.                 Context.MODE_PRIVATE);  
  103.         Editor editor = prefs.edit();  
  104.         editor.putLong(BACKOFF, backoff);  
  105.         editor.commit();  
  106.   
  107.     }  
  108.   
  109.     // package  
  110.     static void clearRegistrationId(Context context) {  
  111.         final SharedPreferences prefs = context.getSharedPreferences(  
  112.                 PREFERENCE,  
  113.                 Context.MODE_PRIVATE);  
  114.         Editor editor = prefs.edit();  
  115.         editor.putString("dm_registration""");  
  116.         editor.putLong(LAST_REGISTRATION_CHANGE, System.currentTimeMillis());  
  117.         editor.commit();  
  118.   
  119.     }  
  120.   
  121.     // package  
  122.     static void setRegistrationId(Context context, String registrationId) {  
  123.         final SharedPreferences prefs = context.getSharedPreferences(  
  124.                 PREFERENCE,  
  125.                 Context.MODE_PRIVATE);  
  126.         Editor editor = prefs.edit();  
  127.         editor.putString("dm_registration", registrationId);  
  128.         editor.commit();  
  129.   
  130.     }  
  131. }  

 

org.wp.activity

 

AndroidC2DMDemo 

Java代码  收藏代码
  1. package org.wp.activity;  
  2.   
  3. import com.google.android.c2dm.C2DMessaging;  
  4.   
  5. import android.app.Activity;  
  6. import android.os.Bundle;  
  7. import android.util.Log;  
  8.   
  9. public class AndroidC2DMDemo extends Activity {  
  10.     private static final String TAG = "AndroidC2DMDemo";  
  11.     public static final String SENDER_ID = "wp.android.c2dm.demo@gmail.com";  
  12.     public static final String MESSAGE_KEY = "onewayonelife";  
  13.   
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.   
  19.         Log.i(TAG, "start");  
  20.         C2DMessaging.register(this, SENDER_ID);  
  21.     }  
  22. }  

 

C2DMReceiver

Java代码  收藏代码
  1. package org.wp.activity;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import android.app.Notification;  
  6. import android.app.NotificationManager;  
  7. import android.app.PendingIntent;  
  8. import android.content.Context;  
  9. import android.content.Intent;  
  10. import android.os.Bundle;  
  11. import android.util.Log;  
  12.   
  13. import com.google.android.c2dm.C2DMBaseReceiver;  
  14.   
  15. public class C2DMReceiver extends C2DMBaseReceiver {  
  16.     private static final String TAG = "C2DMReceiver";  
  17.   
  18.     public C2DMReceiver() {  
  19.         super(AndroidC2DMDemo.SENDER_ID);  
  20.     }  
  21.   
  22.     @Override  
  23.     public void onRegistered(Context context, String registrationId)  
  24.             throws IOException {  
  25.         Log.i(TAG, "registrationId:" + registrationId);  
  26.     }  
  27.   
  28.     @Override  
  29.     public void onUnregistered(Context context) {  
  30.     }  
  31.   
  32.     @Override  
  33.     protected void onMessage(Context context, Intent intent) {  
  34.         Bundle extras = intent.getExtras();  
  35.         if (extras != null) {  
  36.             String msg = extras.getString(AndroidC2DMDemo.MESSAGE_KEY);  
  37.             NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);  
  38.             PendingIntent contentIntent = PendingIntent.getActivity(this0new Intent(this, AndroidC2DMDemo.class), 0);  
  39.             Notification notification = new Notification(R.drawable.icon, msg, System.currentTimeMillis());  
  40.             notification.setLatestEventInfo(this, getString(R.string.app_name), msg, contentIntent);  
  41.             notification.flags |= Notification.FLAG_AUTO_CANCEL;  
  42.             notificationManager.notify(0, notification);  
  43.         }  
  44.     }  
  45.   
  46.     @Override  
  47.     public void onError(Context context, String errorId) {  
  48.     }  
  49. }  

 

AndroidManifest.xml

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="org.wp.activity" android:versionCode="1" android:versionName="1.0">  
  4.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  5.         <activity android:name=".AndroidC2DMDemo" android:label="@string/app_name">  
  6.             <intent-filter>  
  7.                 <action android:name="android.intent.action.MAIN" />  
  8.                 <category android:name="android.intent.category.LAUNCHER" />  
  9.             </intent-filter>  
  10.         </activity>  
  11.         <!-- In order to use the c2dm library, an application must declare a class   
  12.             with the name C2DMReceiver, in its own package,   
  13.             extending com.google.android.c2dm.C2DMBaseReceiver   
  14.             It must also include this section in the manifest. -->  
  15.         <service android:name=".C2DMReceiver" />  
  16.         <!-- Only C2DM servers can send messages for the app. If permission is   
  17.             not set - any other app can generate it -->  
  18.         <receiver android:name="com.google.android.c2dm.C2DMBroadcastReceiver"  
  19.                   android:permission="com.google.android.c2dm.permission.SEND">  
  20.             <!-- Receive the actual message -->  
  21.             <intent-filter>  
  22.                 <action android:name="com.google.android.c2dm.intent.RECEIVE" />  
  23.                 <category android:name="org.wp.activity" />  
  24.             </intent-filter>  
  25.             <!-- Receive the registration id -->  
  26.             <intent-filter>  
  27.                 <action android:name="com.google.android.c2dm.intent.REGISTRATION" />  
  28.                 <category android:name="org.wp.activity" />  
  29.             </intent-filter>  
  30.         </receiver>  
  31.     </application>  
  32.     <uses-sdk android:minSdkVersion="8" />  
  33.   
  34.     <!-- Only this application can receive the messages and registration result -->  
  35.     <permission android:name="org.wp.activity.permission.C2D_MESSAGE"  
  36.         android:protectionLevel="signature" />  
  37.     <uses-permission android:name="org.wp.activity.permission.C2D_MESSAGE" />  
  38.     <!-- This app has permission to register and receive message -->  
  39.     <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />  
  40.     <!-- Send the registration id to the server -->  
  41.     <uses-permission android:name="android.permission.INTERNET" />  
  42.     <!-- App must have this permission to use the library -->  
  43.     <uses-permission android:name="android.permission.WAKE_LOCK" />  
  44.     <uses-permission android:name="android.permission.GET_ACCOUNTS" />  
  45.     <uses-permission android:name="android.permission.USE_CREDENTIALS" />  
  46. </manifest>  

 

AndroidC2DMServerDemo

 

AndroidC2DMServer

Java代码  收藏代码
  1. package org.wp.activity;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.InputStreamReader;  
  5. import java.io.OutputStream;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.URL;  
  8. import java.util.Date;  
  9. import java.util.HashMap;  
  10. import java.util.Map;  
  11.   
  12. public class AndroidC2DMServer {  
  13.     private static String clientLoginUrl = "https://www.google.com/accounts/ClientLogin";  
  14.     // 因为使用https的方式会提示出错,因此使用http的方式  
  15.     private static String pushUrl = "http://android.apis.google.com/c2dm/send";  
  16.     private static String registrationId = "APA91bHeWVX8t0hE-mhks0539soI9JaNFcU1r0_BEtDShnMy0lDDF3U2nR5NxC8F18y_oqj3nbzE3Pn9PpcilYRsK09lnsAaFhRcVCfS0zaztHt6BRXveHey73ipRBeJzpdd9xegxwsQih1B-Dr9Pj903tiorIZbcQ";  
  17.   
  18.     public static void main(String args[]) {  
  19.         // 获取注册使用C2DM服务的用户账号的ClientLogin权限Auth值  
  20.         String auth = getAuthToken(clientLoginUrl, getClientLoginParams());  
  21.         if (auth != null && !"".equals(auth)) {  
  22.             // 按格式给C2DM服务器发送要Push的数据  
  23.             Map<String, String> data = new HashMap<String, String>();  
  24.             data.put("onewayonelife""onewayonelife!" + new Date());  
  25.             sendPushMessage(pushUrl, getPushParams(registrationId, "wp", data, true), auth);  
  26.         }  
  27.     }  
  28.       
  29.     public static String getClientLoginParams() {  
  30.         StringBuilder clsb = new StringBuilder();  
  31.         /** accountType 请求授权的帐户类型 **/  
  32.         clsb.append("accountType=HOSTED_OR_GOOGLE");  
  33.         /** Email 邮箱账号 **/  
  34.         clsb.append("&Email=wp.android.c2dm.demo@gmail.com");  
  35.         /** Passwd 邮箱账号密码 **/  
  36.         clsb.append("&Passwd=wpandroidc2dmdemo");  
  37.         /** service 请求授权的服务名称,C2DM服务的值为ac2dm **/  
  38.         clsb.append("&service=ac2dm");  
  39.         /** source 用来表示我们应用的字符串,类似companyName-applicationName-versionID **/  
  40.         clsb.append("&source=wp-c2dmdemo-1.0");  
  41.         return clsb.toString();  
  42.     }  
  43.   
  44.     public static String getAuthToken(final String url, final String params) {  
  45.         String auth = null;  
  46.         try {  
  47.             byte[] postData = params.getBytes();  
  48.               
  49.             URL requestUrl = new URL(url);  
  50.             HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();  
  51.             // 上传数据,需要将setDoOutput方法的参数值设为true  
  52.             connection.setDoOutput(true);  
  53.             // Post请求不能使用缓存  
  54.             connection.setUseCaches(false);  
  55.             connection.setRequestMethod("POST");  
  56.             connection.setRequestProperty("Content-Type""application/x-www-form-urlencoded");  
  57.             connection.setRequestProperty("Content-Length", Integer.toString(postData.length));  
  58.             connection.setRequestProperty("Charset""UTF-8");  
  59.             OutputStream out = connection.getOutputStream();  
  60.             // 写入POST数据  
  61.             out.write(postData);  
  62.             out.flush();  
  63.             out.close();  
  64.   
  65.             // 请求成功  
  66.             if (connection.getResponseCode() == 200) {  
  67.                 BufferedReader br = new BufferedReader(new InputStreamReader(  
  68.                         connection.getInputStream()));  
  69.                 String responseLine;  
  70.                 StringBuilder sb = new StringBuilder();  
  71.                 while ((responseLine = br.readLine()) != null) {  
  72.                     sb.append(responseLine);  
  73.                 }  
  74.                 auth = sb.substring(sb.indexOf("Auth=") + 5);  
  75.             }  
  76.         } catch (Exception e) {  
  77.             e.printStackTrace();  
  78.         }  
  79.         return auth;  
  80.     }  
  81.       
  82.     public static String getPushParams(String registration_id, String collapse_key,   
  83.             Map<String, String> data, boolean delay_while_idle) {  
  84.         StringBuilder phsb = new StringBuilder();  
  85.         /** registration_id Android应用程序注册获得的id **/  
  86.         phsb.append("registration_id=" + registration_id);  
  87.         /** collapse_key 用一个任意的字符串来标识一组类似的信息 
  88.          * 当设备由离线状态重新上线以后,只有最后一条消息被发送到客户端 
  89.          * 这是为了避免当设备重新上线后有太多的信息发送到手机 **/  
  90.         phsb.append("&collapse_key=" + collapse_key);  
  91.         /** data.<key> 推送的信息,以键值对形式保存 
  92.          * 将会被包含在intent当中发送到android应用程序 
  93.          * 对于个数上并没有限制,只是在数据总大小上有要求 **/  
  94.         for (String key : data.keySet()) {  
  95.             phsb.append("&data." + key + "=" + data.get(key));  
  96.         }  
  97.         /** delay_while_idle 如果包含这个值 
  98.          * 表示不会在设备处于闲置状态的时候就立即发送推送消息 
  99.          * 服务器会等待设备变为活动状态的时候发送 
  100.          * 并且只有collapse_key标识的最后一条信息才会被发送 **/  
  101.         if (delay_while_idle)  
  102.             phsb.append("&delay_while_idle=0");  
  103.         return phsb.toString();  
  104.     }  
  105.   
  106.     public static void sendPushMessage(final String url, final String params, final String auth) {  
  107.         try {  
  108.             byte[] postData = params.getBytes();  
  109.               
  110.             URL requestUrl = new URL(url);  
  111.             HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();  
  112.             // 上传数据,需要将setDoOutput方法的参数值设为true  
  113.             connection.setDoOutput(true);  
  114.             // Post请求不能使用缓存  
  115.             connection.setUseCaches(false);  
  116.             connection.setRequestMethod("POST");  
  117.             connection.setRequestProperty("Content-Type""application/x-www-form-urlencoded");  
  118.             connection.setRequestProperty("Content-Length", Integer.toString(postData.length));  
  119.             connection.setRequestProperty("Charset""UTF-8");  
  120.             connection.setRequestProperty("Authorization""GoogleLogin auth=" + auth);  
  121.             OutputStream out = connection.getOutputStream();  
  122.             out.write(postData);  
  123.             out.flush();  
  124.             out.close();  
  125.   
  126.             int responseCode = connection.getResponseCode();  
  127.             if (responseCode == 200) {  
  128.                 BufferedReader br = new BufferedReader(new InputStreamReader(  
  129.                         connection.getInputStream()));  
  130.                 String responseLine;  
  131.                 StringBuilder sb = new StringBuilder();  
  132.                 while ((responseLine = br.readLine()) != null) {  
  133.                     sb.append(responseLine);  
  134.                 }  
  135.                 if (sb.toString().startsWith("id=")) {  
  136.                     System.out.println("推送信息发送成功!");  
  137.                 }  
  138.             } else if (responseCode == 503) {  
  139.                 System.out.println("Indicates that the server is temporarily unavailable (i.e., because of timeouts, etc ). Sender must retry later, honoring any Retry-After header included in the response. Application servers must implement exponential back off. Senders that create problems risk being blacklisted.");  
  140.             } else if (responseCode == 401) {  
  141.                 System.out.println("Indicates that the ClientLogin AUTH_TOKEN used to validate the sender is invalid.");  
  142.             }  
  143.         } catch (Exception e) {  
  144.             e.printStackTrace();  
  145.         }  
  146.     }  
  147. }