Android C2DM 实现消息推送
博客分类:?- Android
AndroidC2DMDemo
?
com.google.android.c2dm
?
C2DMBroadcastReceiver
Java代码??
- /*?
- ?*/??
- 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.?
- ?*??
- ?*/??
- 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?*/);??????????
- ????}??
- }??
?
C2DMBaseReceiver
Java代码??
- /*?
- ?*?Copyright?2010?Google?Inc.?
- ?*?
- ?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");?
- ?*?you?may?not?use?this?file?except?in?compliance?with?the?License.?
- ?*?You?may?obtain?a?copy?of?the?License?at?
- ?*?
- ?*???http://www.apache.org/licenses/LICENSE-2.0?
- ?*?
- ?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software?
- ?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,?
- ?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.?
- ?*?See?the?License?for?the?specific?language?governing?permissions?and?
- ?*?limitations?under?the?License.?
- ?*/??
- ??
- package?com.google.android.c2dm;??
- ??
- import?java.io.IOException;??
- ??
- import?android.app.AlarmManager;??
- import?android.app.IntentService;??
- import?android.app.PendingIntent;??
- import?android.content.Context;??
- import?android.content.Intent;??
- import?android.os.PowerManager;??
- import?android.util.Log;??
- ??
- /**?
- ?*?Base?class?for?C2D?message?receiver.?Includes?constants?for?the?
- ?*?strings?used?in?the?protocol.?
- ?*/??
- public?abstract?class?C2DMBaseReceiver?extends?IntentService?{??
- ????private?static?final?String?C2DM_RETRY?=?"com.google.android.c2dm.intent.RETRY";??
- ??
- ????public?static?final?String?REGISTRATION_CALLBACK_INTENT?=?"com.google.android.c2dm.intent.REGISTRATION";??
- ????private?static?final?String?C2DM_INTENT?=?"com.google.android.c2dm.intent.RECEIVE";??
- ??
- ????//?Logging?tag??
- ????private?static?final?String?TAG?=?"C2DM";??
- ??
- ????//?Extras?in?the?registration?callback?intents.??
- ????public?static?final?String?EXTRA_UNREGISTERED?=?"unregistered";??
- ??
- ????public?static?final?String?EXTRA_ERROR?=?"error";??
- ??
- ????public?static?final?String?EXTRA_REGISTRATION_ID?=?"registration_id";??
- ??
- ????public?static?final?String?ERR_SERVICE_NOT_AVAILABLE?=?"SERVICE_NOT_AVAILABLE";??
- ????public?static?final?String?ERR_ACCOUNT_MISSING?=?"ACCOUNT_MISSING";??
- ????public?static?final?String?ERR_AUTHENTICATION_FAILED?=?"AUTHENTICATION_FAILED";??
- ????public?static?final?String?ERR_TOO_MANY_REGISTRATIONS?=?"TOO_MANY_REGISTRATIONS";??
- ????public?static?final?String?ERR_INVALID_PARAMETERS?=?"INVALID_PARAMETERS";??
- ????public?static?final?String?ERR_INVALID_SENDER?=?"INVALID_SENDER";??
- ????public?static?final?String?ERR_PHONE_REGISTRATION_ERROR?=?"PHONE_REGISTRATION_ERROR";??
- ??????
- ????//?wakelock??
- ????private?static?final?String?WAKELOCK_KEY?=?"C2DM_LIB";??
- ??
- ????private?static?PowerManager.WakeLock?mWakeLock;??
- ????private?final?String?senderId;??
- ??
- ????/**?
- ?????*?The?C2DMReceiver?class?must?create?a?no-arg?constructor?and?pass?the??
- ?????*?sender?id?to?be?used?for?registration.?
- ?????*/??
- ????public?C2DMBaseReceiver(String?senderId)?{??
- ????????//?senderId?is?used?as?base?name?for?threads,?etc.??
- ????????super(senderId);??
- ????????this.senderId?=?senderId;??
- ????}??
- ??????
- ????/**?
- ?????*?Called?when?a?cloud?message?has?been?received.?
- ?????*/??
- ????protected?abstract?void?onMessage(Context?context,?Intent?intent);??
- ??
- ????/**?
- ?????*?Called?on?registration?error.?Override?to?provide?better?
- ?????*?error?messages.?
- ?????*???
- ?????*?This?is?called?in?the?context?of?a?Service?-?no?dialog?or?UI.?
- ?????*/??
- ????public?abstract?void?onError(Context?context,?String?errorId);??
- ??
- ????/**?
- ?????*?Called?when?a?registration?token?has?been?received.?
- ?????*/??
- ????public?void?onRegistered(Context?context,?String?registrationId)?throws?IOException?{??
- ????????//?registrationId?will?also?be?saved??
- ????}??
- ??
- ????/**?
- ?????*?Called?when?the?device?has?been?unregistered.?
- ?????*/??
- ????public?void?onUnregistered(Context?context)?{??
- ????}??
- ??
- ??????
- ????@Override??
- ????public?final?void?onHandleIntent(Intent?intent)?{??
- ????????try?{??
- ????????????Context?context?=?getApplicationContext();??
- ????????????if?(intent.getAction().equals(REGISTRATION_CALLBACK_INTENT))?{??
- ????????????????handleRegistration(context,?intent);??
- ????????????}?else?if?(intent.getAction().equals(C2DM_INTENT))?{??
- ????????????????onMessage(context,?intent);??
- ????????????}?else?if?(intent.getAction().equals(C2DM_RETRY))?{??
- ????????????????C2DMessaging.register(context,?senderId);??
- ????????????}??
- ????????}?finally?{??
- ????????????//??Release?the?power?lock,?so?phone?can?get?back?to?sleep.??
- ????????????//?The?lock?is?reference?counted?by?default,?so?multiple???
- ????????????//?messages?are?ok.??
- ??????????????
- ????????????//?If?the?onMessage()?needs?to?spawn?a?thread?or?do?something?else,??
- ????????????//?it?should?use?it's?own?lock.??
- ????????????mWakeLock.release();??
- ????????}??
- ????}??
- ??
- ??????
- ????/**?
- ?????*?Called?from?the?broadcast?receiver.??
- ?????*?Will?process?the?received?intent,?call?handleMessage(),?registered(),?etc.?
- ?????*?in?background?threads,?with?a?wake?lock,?while?keeping?the?service??
- ?????*?alive.??
- ?????*/??
- ????static?void?runIntentInService(Context?context,?Intent?intent)?{??
- ????????if?(mWakeLock?==?null)?{??
- ????????????//?This?is?called?from?BroadcastReceiver,?there?is?no?init.??
- ????????????PowerManager?pm?=???
- ????????????????(PowerManager)?context.getSystemService(Context.POWER_SERVICE);??
- ????????????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);??
- ??
- ????????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());??
- ????????????}??
- ????????}??
- ????}??
- }??
?
C2DMessaging
Java代码??
- /*?
- ?*?Copyright?2010?Google?Inc.?
- ?*?
- ?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");?
- ?*?you?may?not?use?this?file?except?in?compliance?with?the?License.?
- ?*?You?may?obtain?a?copy?of?the?License?at?
- ?*?
- ?*???http://www.apache.org/licenses/LICENSE-2.0?
- ?*?
- ?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software?
- ?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,?
- ?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.?
- ?*?See?the?License?for?the?specific?language?governing?permissions?and?
- ?*?limitations?under?the?License.?
- ?*/??
- ??
- 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";??
- ??
- ??
- ????//?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();??
- ??
- ????}??
- }??
?
org.wp.activity
?
AndroidC2DMDemo?
Java代码??
- package?org.wp.activity;??
- ??
- import?com.google.android.c2dm.C2DMessaging;??
- ??
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.util.Log;??
- ??
- public?class?AndroidC2DMDemo?extends?Activity?{??
- ????private?static?final?String?TAG?=?"AndroidC2DMDemo";??
- ????public?static?final?String?SENDER_ID?=?"wp.android.c2dm.demo@gmail.com";??
- ????public?static?final?String?MESSAGE_KEY?=?"onewayonelife";??
- ??
- ????@Override??
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????????super.onCreate(savedInstanceState);??
- ????????setContentView(R.layout.main);??
- ??
- ????????Log.i(TAG,?"start");??
- ????????C2DMessaging.register(this,?SENDER_ID);??
- ????}??
- }??
?
C2DMReceiver
Java代码??
- package?org.wp.activity;??
- ??
- 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;??
- ??
- public?class?C2DMReceiver?extends?C2DMBaseReceiver?{??
- ????private?static?final?String?TAG?=?"C2DMReceiver";??
- ??
- ????public?C2DMReceiver()?{??
- ????????super(AndroidC2DMDemo.SENDER_ID);??
- ????}??
- ??
- ????@Override??
- ????public?void?onRegistered(Context?context,?String?registrationId)??
- ????????????throws?IOException?{??
- ????????Log.i(TAG,?"registrationId:"?+?registrationId);??
- ????}??
- ??
- ????@Override??
- ????public?void?onUnregistered(Context?context)?{??
- ????}??
- ??
- ????@Override??
- ????protected?void?onMessage(Context?context,?Intent?intent)?{??
- ????????Bundle?extras?=?intent.getExtras();??
- ????????if?(extras?!=?null)?{??
- ????????????String?msg?=?extras.getString(AndroidC2DMDemo.MESSAGE_KEY);??
- ????????????NotificationManager?notificationManager?=?(NotificationManager)?getSystemService(NOTIFICATION_SERVICE);??
- ????????????PendingIntent?contentIntent?=?PendingIntent.getActivity(this,?0,?new?Intent(this,?AndroidC2DMDemo.class),?0);??
- ????????????Notification?notification?=?new?Notification(R.drawable.icon,?msg,?System.currentTimeMillis());??
- ????????????notification.setLatestEventInfo(this,?getString(R.string.app_name),?msg,?contentIntent);??
- ????????????notification.flags?|=?Notification.FLAG_AUTO_CANCEL;??
- ????????????notificationManager.notify(0,?notification);??
- ????????}??
- ????}??
- ??
- ????@Override??
- ????public?void?onError(Context?context,?String?errorId)?{??
- ????}??
- }??
?
AndroidManifest.xml
Xml代码??
- <?xml?version="1.0"?encoding="utf-8"?>??
- <manifest?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????package="org.wp.activity"?android:versionCode="1"?android:versionName="1.0">??
- ????<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.?-->??
- ????????<service?android:name=".C2DMReceiver"?/>??
- ????????<!--?Only?C2DM?servers?can?send?messages?for?the?app.?If?permission?is???
- ????????????not?set?-?any?other?app?can?generate?it?-->??
- ????????<receiver?android:name="com.google.android.c2dm.C2DMBroadcastReceiver"??
- ??????????????????android:permission="com.google.android.c2dm.permission.SEND">??
- ????????????<!--?Receive?the?actual?message?-->??
- ????????????<intent-filter>??
- ????????????????<action?android:name="com.google.android.c2dm.intent.RECEIVE"?/>??
- ????????????????<category?android:name="org.wp.activity"?/>??
- ????????????</intent-filter>??
- ????????????<!--?Receive?the?registration?id?-->??
- ????????????<intent-filter>??
- ????????????????<action?android:name="com.google.android.c2dm.intent.REGISTRATION"?/>??
- ????????????????<category?android:name="org.wp.activity"?/>??
- ????????????</intent-filter>??
- ????????</receiver>??
- ????</application>??
- ????<uses-sdk?android:minSdkVersion="8"?/>??
- ??
- ????<!--?Only?this?application?can?receive?the?messages?and?registration?result?-->??
- ????<permission?android:name="org.wp.activity.permission.C2D_MESSAGE"??
- ????????android:protectionLevel="signature"?/>??
- ????<uses-permission?android:name="org.wp.activity.permission.C2D_MESSAGE"?/>??
- ????<!--?This?app?has?permission?to?register?and?receive?message?-->??
- ????<uses-permission?android:name="com.google.android.c2dm.permission.RECEIVE"?/>??
- ????<!--?Send?the?registration?id?to?the?server?-->??
- ????<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"?/>??
- </manifest>??
?
AndroidC2DMServerDemo
?
AndroidC2DMServer
Java代码??
- package?org.wp.activity;??
- ??
- import?java.io.BufferedReader;??
- import?java.io.InputStreamReader;??
- import?java.io.OutputStream;??
- import?java.net.HttpURLConnection;??
- import?java.net.URL;??
- import?java.util.Date;??
- import?java.util.HashMap;??
- import?java.util.Map;??
- ??
- public?class?AndroidC2DMServer?{??
- ????private?static?String?clientLoginUrl?=?"https://www.google.com/accounts/ClientLogin";??
- ????//?因为使用https的方式会提示出错,因此使用http的方式??
- ????private?static?String?pushUrl?=?"http://android.apis.google.com/c2dm/send";??
- ????private?static?String?registrationId?=?"APA91bHeWVX8t0hE-mhks0539soI9JaNFcU1r0_BEtDShnMy0lDDF3U2nR5NxC8F18y_oqj3nbzE3Pn9PpcilYRsK09lnsAaFhRcVCfS0zaztHt6BRXveHey73ipRBeJzpdd9xegxwsQih1B-Dr9Pj903tiorIZbcQ";??
- ??
- ????public?static?void?main(String?args[])?{??
- ????????//?获取注册使用C2DM服务的用户账号的ClientLogin权限Auth值??
- ????????String?auth?=?getAuthToken(clientLoginUrl,?getClientLoginParams());??
- ????????if?(auth?!=?null?&&?!"".equals(auth))?{??
- ????????????//?按格式给C2DM服务器发送要Push的数据??
- ????????????Map<String,?String>?data?=?new?HashMap<String,?String>();??
- ????????????data.put("onewayonelife",?"onewayonelife!"?+?new?Date());??
- ????????????sendPushMessage(pushUrl,?getPushParams(registrationId,?"wp",?data,?true),?auth);??
- ????????}??
- ????}??
- ??????
- ????public?static?String?getClientLoginParams()?{??
- ????????StringBuilder?clsb?=?new?StringBuilder();??
- ????????/**?accountType?请求授权的帐户类型?**/??
- ????????clsb.append("accountType=HOSTED_OR_GOOGLE");??
- ????????/**?Email?邮箱账号?**/??
- ????????clsb.append("&Email=wp.android.c2dm.demo@gmail.com");??
- ????????/**?Passwd?邮箱账号密码?**/??
- ????????clsb.append("&Passwd=wpandroidc2dmdemo");??
- ????????/**?service?请求授权的服务名称,C2DM服务的值为ac2dm?**/??
- ????????clsb.append("&service=ac2dm");??
- ????????/**?source?用来表示我们应用的字符串,类似companyName-applicationName-versionID?**/??
- ????????clsb.append("&source=wp-c2dmdemo-1.0");??
- ????????return?clsb.toString();??
- ????}??
- ??
- ????public?static?String?getAuthToken(final?String?url,?final?String?params)?{??
- ????????String?auth?=?null;??
- ????????try?{??
- ????????????byte[]?postData?=?params.getBytes();??
- ??????????????
- ????????????URL?requestUrl?=?new?URL(url);??
- ????????????HttpURLConnection?connection?=?(HttpURLConnection)?requestUrl.openConnection();??
- ????????????//?上传数据,需要将setDoOutput方法的参数值设为true??
- ????????????connection.setDoOutput(true);??
- ????????????//?Post请求不能使用缓存??
- ????????????connection.setUseCaches(false);??
- ????????????connection.setRequestMethod("POST");??
- ????????????connection.setRequestProperty("Content-Type",?"application/x-www-form-urlencoded");??
- ????????????connection.setRequestProperty("Content-Length",?Integer.toString(postData.length));??
- ????????????connection.setRequestProperty("Charset",?"UTF-8");??
- ????????????OutputStream?out?=?connection.getOutputStream();??
- ????????????//?写入POST数据??
- ????????????out.write(postData);??
- ????????????out.flush();??
- ????????????out.close();??
- ??
- ????????????//?请求成功??
- ????????????if?(connection.getResponseCode()?==?200)?{??
- ????????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(??
- ????????????????????????connection.getInputStream()));??
- ????????????????String?responseLine;??
- ????????????????StringBuilder?sb?=?new?StringBuilder();??
- ????????????????while?((responseLine?=?br.readLine())?!=?null)?{??
- ????????????????????sb.append(responseLine);??
- ????????????????}??
- ????????????????auth?=?sb.substring(sb.indexOf("Auth=")?+?5);??
- ????????????}??
- ????????}?catch?(Exception?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????return?auth;??
- ????}??
- ??????
- ????public?static?String?getPushParams(String?registration_id,?String?collapse_key,???
- ????????????Map<String,?String>?data,?boolean?delay_while_idle)?{??
- ????????StringBuilder?phsb?=?new?StringBuilder();??
- ????????/**?registration_id?Android应用程序注册获得的id?**/??
- ????????phsb.append("registration_id="?+?registration_id);??
- ????????/**?collapse_key?用一个任意的字符串来标识一组类似的信息?
- ?????????*?当设备由离线状态重新上线以后,只有最后一条消息被发送到客户端?
- ?????????*?这是为了避免当设备重新上线后有太多的信息发送到手机?**/??
- ????????phsb.append("&collapse_key="?+?collapse_key);??
- ????????/**?data.<key>?推送的信息,以键值对形式保存?
- ?????????*?将会被包含在intent当中发送到android应用程序?
- ?????????*?对于个数上并没有限制,只是在数据总大小上有要求?**/??
- ????????for?(String?key?:?data.keySet())?{??
- ????????????phsb.append("&data."?+?key?+?"="?+?data.get(key));??
- ????????}??
- ????????/**?delay_while_idle?如果包含这个值?
- ?????????*?表示不会在设备处于闲置状态的时候就立即发送推送消息?
- ?????????*?服务器会等待设备变为活动状态的时候发送?
- ?????????*?并且只有collapse_key标识的最后一条信息才会被发送?**/??
- ????????if?(delay_while_idle)??
- ????????????phsb.append("&delay_while_idle=0");??
- ????????return?phsb.toString();??
- ????}??
- ??
- ????public?static?void?sendPushMessage(final?String?url,?final?String?params,?final?String?auth)?{??
- ????????try?{??
- ????????????byte[]?postData?=?params.getBytes();??
- ??????????????
- ????????????URL?requestUrl?=?new?URL(url);??
- ????????????HttpURLConnection?connection?=?(HttpURLConnection)?requestUrl.openConnection();??
- ????????????//?上传数据,需要将setDoOutput方法的参数值设为true??
- ????????????connection.setDoOutput(true);??
- ????????????//?Post请求不能使用缓存??
- ????????????connection.setUseCaches(false);??
- ????????????connection.setRequestMethod("POST");??
- ????????????connection.setRequestProperty("Content-Type",?"application/x-www-form-urlencoded");??
- ????????????connection.setRequestProperty("Content-Length",?Integer.toString(postData.length));??
- ????????????connection.setRequestProperty("Charset",?"UTF-8");??
- ????????????connection.setRequestProperty("Authorization",?"GoogleLogin?auth="?+?auth);??
- ????????????OutputStream?out?=?connection.getOutputStream();??
- ????????????out.write(postData);??
- ????????????out.flush();??
- ????????????out.close();??
- ??
- ????????????int?responseCode?=?connection.getResponseCode();??
- ????????????if?(responseCode?==?200)?{??
- ????????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(??
- ????????????????????????connection.getInputStream()));??
- ????????????????String?responseLine;??
- ????????????????StringBuilder?sb?=?new?StringBuilder();??
- ????????????????while?((responseLine?=?br.readLine())?!=?null)?{??
- ????????????????????sb.append(responseLine);??
- ????????????????}??
- ????????????????if?(sb.toString().startsWith("id="))?{??
- ????????????????????System.out.println("推送信息发送成功!");??
- ????????????????}??
- ????????????}?else?if?(responseCode?==?503)?{??
- ????????????????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.");??
- ????????????}?else?if?(responseCode?==?401)?{??
- ????????????????System.out.println("Indicates?that?the?ClientLogin?AUTH_TOKEN?used?to?validate?the?sender?is?invalid.");??
- ????????????}??
- ????????}?catch?(Exception?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????}??
- }??
?
?
1 楼 William_Duan 2011-10-11 这种方式在国内能用吗?感觉被限制了。 2 楼 pgy20032000 2011-10-11 William_Duan 写道这种方式在国内能用吗?感觉被限制了。
我还没来得及试 这是从一个朋友那转的 3 楼 wulingbo2005 2012-01-11 为什么现在注册收不到广播??
AndroidC2DMDemo
?
com.google.android.c2dm
?
C2DMBroadcastReceiver
Java代码??
- /*?
- ?*/??
- 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.?
- ?*??
- ?*/??
- 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?*/);??????????
- ????}??
- }??
?
C2DMBaseReceiver
Java代码??
- /*?
- ?*?Copyright?2010?Google?Inc.?
- ?*?
- ?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");?
- ?*?you?may?not?use?this?file?except?in?compliance?with?the?License.?
- ?*?You?may?obtain?a?copy?of?the?License?at?
- ?*?
- ?*???http://www.apache.org/licenses/LICENSE-2.0?
- ?*?
- ?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software?
- ?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,?
- ?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.?
- ?*?See?the?License?for?the?specific?language?governing?permissions?and?
- ?*?limitations?under?the?License.?
- ?*/??
- ??
- package?com.google.android.c2dm;??
- ??
- import?java.io.IOException;??
- ??
- import?android.app.AlarmManager;??
- import?android.app.IntentService;??
- import?android.app.PendingIntent;??
- import?android.content.Context;??
- import?android.content.Intent;??
- import?android.os.PowerManager;??
- import?android.util.Log;??
- ??
- /**?
- ?*?Base?class?for?C2D?message?receiver.?Includes?constants?for?the?
- ?*?strings?used?in?the?protocol.?
- ?*/??
- public?abstract?class?C2DMBaseReceiver?extends?IntentService?{??
- ????private?static?final?String?C2DM_RETRY?=?"com.google.android.c2dm.intent.RETRY";??
- ??
- ????public?static?final?String?REGISTRATION_CALLBACK_INTENT?=?"com.google.android.c2dm.intent.REGISTRATION";??
- ????private?static?final?String?C2DM_INTENT?=?"com.google.android.c2dm.intent.RECEIVE";??
- ??
- ????//?Logging?tag??
- ????private?static?final?String?TAG?=?"C2DM";??
- ??
- ????//?Extras?in?the?registration?callback?intents.??
- ????public?static?final?String?EXTRA_UNREGISTERED?=?"unregistered";??
- ??
- ????public?static?final?String?EXTRA_ERROR?=?"error";??
- ??
- ????public?static?final?String?EXTRA_REGISTRATION_ID?=?"registration_id";??
- ??
- ????public?static?final?String?ERR_SERVICE_NOT_AVAILABLE?=?"SERVICE_NOT_AVAILABLE";??
- ????public?static?final?String?ERR_ACCOUNT_MISSING?=?"ACCOUNT_MISSING";??
- ????public?static?final?String?ERR_AUTHENTICATION_FAILED?=?"AUTHENTICATION_FAILED";??
- ????public?static?final?String?ERR_TOO_MANY_REGISTRATIONS?=?"TOO_MANY_REGISTRATIONS";??
- ????public?static?final?String?ERR_INVALID_PARAMETERS?=?"INVALID_PARAMETERS";??
- ????public?static?final?String?ERR_INVALID_SENDER?=?"INVALID_SENDER";??
- ????public?static?final?String?ERR_PHONE_REGISTRATION_ERROR?=?"PHONE_REGISTRATION_ERROR";??
- ??????
- ????//?wakelock??
- ????private?static?final?String?WAKELOCK_KEY?=?"C2DM_LIB";??
- ??
- ????private?static?PowerManager.WakeLock?mWakeLock;??
- ????private?final?String?senderId;??
- ??
- ????/**?
- ?????*?The?C2DMReceiver?class?must?create?a?no-arg?constructor?and?pass?the??
- ?????*?sender?id?to?be?used?for?registration.?
- ?????*/??
- ????public?C2DMBaseReceiver(String?senderId)?{??
- ????????//?senderId?is?used?as?base?name?for?threads,?etc.??
- ????????super(senderId);??
- ????????this.senderId?=?senderId;??
- ????}??
- ??????
- ????/**?
- ?????*?Called?when?a?cloud?message?has?been?received.?
- ?????*/??
- ????protected?abstract?void?onMessage(Context?context,?Intent?intent);??
- ??
- ????/**?
- ?????*?Called?on?registration?error.?Override?to?provide?better?
- ?????*?error?messages.?
- ?????*???
- ?????*?This?is?called?in?the?context?of?a?Service?-?no?dialog?or?UI.?
- ?????*/??
- ????public?abstract?void?onError(Context?context,?String?errorId);??
- ??
- ????/**?
- ?????*?Called?when?a?registration?token?has?been?received.?
- ?????*/??
- ????public?void?onRegistered(Context?context,?String?registrationId)?throws?IOException?{??
- ????????//?registrationId?will?also?be?saved??
- ????}??
- ??
- ????/**?
- ?????*?Called?when?the?device?has?been?unregistered.?
- ?????*/??
- ????public?void?onUnregistered(Context?context)?{??
- ????}??
- ??
- ??????
- ????@Override??
- ????public?final?void?onHandleIntent(Intent?intent)?{??
- ????????try?{??
- ????????????Context?context?=?getApplicationContext();??
- ????????????if?(intent.getAction().equals(REGISTRATION_CALLBACK_INTENT))?{??
- ????????????????handleRegistration(context,?intent);??
- ????????????}?else?if?(intent.getAction().equals(C2DM_INTENT))?{??
- ????????????????onMessage(context,?intent);??
- ????????????}?else?if?(intent.getAction().equals(C2DM_RETRY))?{??
- ????????????????C2DMessaging.register(context,?senderId);??
- ????????????}??
- ????????}?finally?{??
- ????????????//??Release?the?power?lock,?so?phone?can?get?back?to?sleep.??
- ????????????//?The?lock?is?reference?counted?by?default,?so?multiple???
- ????????????//?messages?are?ok.??
- ??????????????
- ????????????//?If?the?onMessage()?needs?to?spawn?a?thread?or?do?something?else,??
- ????????????//?it?should?use?it's?own?lock.??
- ????????????mWakeLock.release();??
- ????????}??
- ????}??
- ??
- ??????
- ????/**?
- ?????*?Called?from?the?broadcast?receiver.??
- ?????*?Will?process?the?received?intent,?call?handleMessage(),?registered(),?etc.?
- ?????*?in?background?threads,?with?a?wake?lock,?while?keeping?the?service??
- ?????*?alive.??
- ?????*/??
- ????static?void?runIntentInService(Context?context,?Intent?intent)?{??
- ????????if?(mWakeLock?==?null)?{??
- ????????????//?This?is?called?from?BroadcastReceiver,?there?is?no?init.??
- ????????????PowerManager?pm?=???
- ????????????????(PowerManager)?context.getSystemService(Context.POWER_SERVICE);??
- ????????????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);??
- ??
- ????????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());??
- ????????????}??
- ????????}??
- ????}??
- }??
?
C2DMessaging
Java代码??
- /*?
- ?*?Copyright?2010?Google?Inc.?
- ?*?
- ?*?Licensed?under?the?Apache?License,?Version?2.0?(the?"License");?
- ?*?you?may?not?use?this?file?except?in?compliance?with?the?License.?
- ?*?You?may?obtain?a?copy?of?the?License?at?
- ?*?
- ?*???http://www.apache.org/licenses/LICENSE-2.0?
- ?*?
- ?*?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software?
- ?*?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS,?
- ?*?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied.?
- ?*?See?the?License?for?the?specific?language?governing?permissions?and?
- ?*?limitations?under?the?License.?
- ?*/??
- ??
- 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";??
- ??
- ??
- ????//?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();??
- ??
- ????}??
- }??
?
org.wp.activity
?
AndroidC2DMDemo?
Java代码??
- package?org.wp.activity;??
- ??
- import?com.google.android.c2dm.C2DMessaging;??
- ??
- import?android.app.Activity;??
- import?android.os.Bundle;??
- import?android.util.Log;??
- ??
- public?class?AndroidC2DMDemo?extends?Activity?{??
- ????private?static?final?String?TAG?=?"AndroidC2DMDemo";??
- ????public?static?final?String?SENDER_ID?=?"wp.android.c2dm.demo@gmail.com";??
- ????public?static?final?String?MESSAGE_KEY?=?"onewayonelife";??
- ??
- ????@Override??
- ????public?void?onCreate(Bundle?savedInstanceState)?{??
- ????????super.onCreate(savedInstanceState);??
- ????????setContentView(R.layout.main);??
- ??
- ????????Log.i(TAG,?"start");??
- ????????C2DMessaging.register(this,?SENDER_ID);??
- ????}??
- }??
?
C2DMReceiver
Java代码??
- package?org.wp.activity;??
- ??
- 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;??
- ??
- public?class?C2DMReceiver?extends?C2DMBaseReceiver?{??
- ????private?static?final?String?TAG?=?"C2DMReceiver";??
- ??
- ????public?C2DMReceiver()?{??
- ????????super(AndroidC2DMDemo.SENDER_ID);??
- ????}??
- ??
- ????@Override??
- ????public?void?onRegistered(Context?context,?String?registrationId)??
- ????????????throws?IOException?{??
- ????????Log.i(TAG,?"registrationId:"?+?registrationId);??
- ????}??
- ??
- ????@Override??
- ????public?void?onUnregistered(Context?context)?{??
- ????}??
- ??
- ????@Override??
- ????protected?void?onMessage(Context?context,?Intent?intent)?{??
- ????????Bundle?extras?=?intent.getExtras();??
- ????????if?(extras?!=?null)?{??
- ????????????String?msg?=?extras.getString(AndroidC2DMDemo.MESSAGE_KEY);??
- ????????????NotificationManager?notificationManager?=?(NotificationManager)?getSystemService(NOTIFICATION_SERVICE);??
- ????????????PendingIntent?contentIntent?=?PendingIntent.getActivity(this,?0,?new?Intent(this,?AndroidC2DMDemo.class),?0);??
- ????????????Notification?notification?=?new?Notification(R.drawable.icon,?msg,?System.currentTimeMillis());??
- ????????????notification.setLatestEventInfo(this,?getString(R.string.app_name),?msg,?contentIntent);??
- ????????????notification.flags?|=?Notification.FLAG_AUTO_CANCEL;??
- ????????????notificationManager.notify(0,?notification);??
- ????????}??
- ????}??
- ??
- ????@Override??
- ????public?void?onError(Context?context,?String?errorId)?{??
- ????}??
- }??
?
AndroidManifest.xml
Xml代码??
- <?xml?version="1.0"?encoding="utf-8"?>??
- <manifest?xmlns:android="http://schemas.android.com/apk/res/android"??
- ????package="org.wp.activity"?android:versionCode="1"?android:versionName="1.0">??
- ????<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.?-->??
- ????????<service?android:name=".C2DMReceiver"?/>??
- ????????<!--?Only?C2DM?servers?can?send?messages?for?the?app.?If?permission?is???
- ????????????not?set?-?any?other?app?can?generate?it?-->??
- ????????<receiver?android:name="com.google.android.c2dm.C2DMBroadcastReceiver"??
- ??????????????????android:permission="com.google.android.c2dm.permission.SEND">??
- ????????????<!--?Receive?the?actual?message?-->??
- ????????????<intent-filter>??
- ????????????????<action?android:name="com.google.android.c2dm.intent.RECEIVE"?/>??
- ????????????????<category?android:name="org.wp.activity"?/>??
- ????????????</intent-filter>??
- ????????????<!--?Receive?the?registration?id?-->??
- ????????????<intent-filter>??
- ????????????????<action?android:name="com.google.android.c2dm.intent.REGISTRATION"?/>??
- ????????????????<category?android:name="org.wp.activity"?/>??
- ????????????</intent-filter>??
- ????????</receiver>??
- ????</application>??
- ????<uses-sdk?android:minSdkVersion="8"?/>??
- ??
- ????<!--?Only?this?application?can?receive?the?messages?and?registration?result?-->??
- ????<permission?android:name="org.wp.activity.permission.C2D_MESSAGE"??
- ????????android:protectionLevel="signature"?/>??
- ????<uses-permission?android:name="org.wp.activity.permission.C2D_MESSAGE"?/>??
- ????<!--?This?app?has?permission?to?register?and?receive?message?-->??
- ????<uses-permission?android:name="com.google.android.c2dm.permission.RECEIVE"?/>??
- ????<!--?Send?the?registration?id?to?the?server?-->??
- ????<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"?/>??
- </manifest>??
?
AndroidC2DMServerDemo
?
AndroidC2DMServer
Java代码??
- package?org.wp.activity;??
- ??
- import?java.io.BufferedReader;??
- import?java.io.InputStreamReader;??
- import?java.io.OutputStream;??
- import?java.net.HttpURLConnection;??
- import?java.net.URL;??
- import?java.util.Date;??
- import?java.util.HashMap;??
- import?java.util.Map;??
- ??
- public?class?AndroidC2DMServer?{??
- ????private?static?String?clientLoginUrl?=?"https://www.google.com/accounts/ClientLogin";??
- ????//?因为使用https的方式会提示出错,因此使用http的方式??
- ????private?static?String?pushUrl?=?"http://android.apis.google.com/c2dm/send";??
- ????private?static?String?registrationId?=?"APA91bHeWVX8t0hE-mhks0539soI9JaNFcU1r0_BEtDShnMy0lDDF3U2nR5NxC8F18y_oqj3nbzE3Pn9PpcilYRsK09lnsAaFhRcVCfS0zaztHt6BRXveHey73ipRBeJzpdd9xegxwsQih1B-Dr9Pj903tiorIZbcQ";??
- ??
- ????public?static?void?main(String?args[])?{??
- ????????//?获取注册使用C2DM服务的用户账号的ClientLogin权限Auth值??
- ????????String?auth?=?getAuthToken(clientLoginUrl,?getClientLoginParams());??
- ????????if?(auth?!=?null?&&?!"".equals(auth))?{??
- ????????????//?按格式给C2DM服务器发送要Push的数据??
- ????????????Map<String,?String>?data?=?new?HashMap<String,?String>();??
- ????????????data.put("onewayonelife",?"onewayonelife!"?+?new?Date());??
- ????????????sendPushMessage(pushUrl,?getPushParams(registrationId,?"wp",?data,?true),?auth);??
- ????????}??
- ????}??
- ??????
- ????public?static?String?getClientLoginParams()?{??
- ????????StringBuilder?clsb?=?new?StringBuilder();??
- ????????/**?accountType?请求授权的帐户类型?**/??
- ????????clsb.append("accountType=HOSTED_OR_GOOGLE");??
- ????????/**?Email?邮箱账号?**/??
- ????????clsb.append("&Email=wp.android.c2dm.demo@gmail.com");??
- ????????/**?Passwd?邮箱账号密码?**/??
- ????????clsb.append("&Passwd=wpandroidc2dmdemo");??
- ????????/**?service?请求授权的服务名称,C2DM服务的值为ac2dm?**/??
- ????????clsb.append("&service=ac2dm");??
- ????????/**?source?用来表示我们应用的字符串,类似companyName-applicationName-versionID?**/??
- ????????clsb.append("&source=wp-c2dmdemo-1.0");??
- ????????return?clsb.toString();??
- ????}??
- ??
- ????public?static?String?getAuthToken(final?String?url,?final?String?params)?{??
- ????????String?auth?=?null;??
- ????????try?{??
- ????????????byte[]?postData?=?params.getBytes();??
- ??????????????
- ????????????URL?requestUrl?=?new?URL(url);??
- ????????????HttpURLConnection?connection?=?(HttpURLConnection)?requestUrl.openConnection();??
- ????????????//?上传数据,需要将setDoOutput方法的参数值设为true??
- ????????????connection.setDoOutput(true);??
- ????????????//?Post请求不能使用缓存??
- ????????????connection.setUseCaches(false);??
- ????????????connection.setRequestMethod("POST");??
- ????????????connection.setRequestProperty("Content-Type",?"application/x-www-form-urlencoded");??
- ????????????connection.setRequestProperty("Content-Length",?Integer.toString(postData.length));??
- ????????????connection.setRequestProperty("Charset",?"UTF-8");??
- ????????????OutputStream?out?=?connection.getOutputStream();??
- ????????????//?写入POST数据??
- ????????????out.write(postData);??
- ????????????out.flush();??
- ????????????out.close();??
- ??
- ????????????//?请求成功??
- ????????????if?(connection.getResponseCode()?==?200)?{??
- ????????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(??
- ????????????????????????connection.getInputStream()));??
- ????????????????String?responseLine;??
- ????????????????StringBuilder?sb?=?new?StringBuilder();??
- ????????????????while?((responseLine?=?br.readLine())?!=?null)?{??
- ????????????????????sb.append(responseLine);??
- ????????????????}??
- ????????????????auth?=?sb.substring(sb.indexOf("Auth=")?+?5);??
- ????????????}??
- ????????}?catch?(Exception?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????????return?auth;??
- ????}??
- ??????
- ????public?static?String?getPushParams(String?registration_id,?String?collapse_key,???
- ????????????Map<String,?String>?data,?boolean?delay_while_idle)?{??
- ????????StringBuilder?phsb?=?new?StringBuilder();??
- ????????/**?registration_id?Android应用程序注册获得的id?**/??
- ????????phsb.append("registration_id="?+?registration_id);??
- ????????/**?collapse_key?用一个任意的字符串来标识一组类似的信息?
- ?????????*?当设备由离线状态重新上线以后,只有最后一条消息被发送到客户端?
- ?????????*?这是为了避免当设备重新上线后有太多的信息发送到手机?**/??
- ????????phsb.append("&collapse_key="?+?collapse_key);??
- ????????/**?data.<key>?推送的信息,以键值对形式保存?
- ?????????*?将会被包含在intent当中发送到android应用程序?
- ?????????*?对于个数上并没有限制,只是在数据总大小上有要求?**/??
- ????????for?(String?key?:?data.keySet())?{??
- ????????????phsb.append("&data."?+?key?+?"="?+?data.get(key));??
- ????????}??
- ????????/**?delay_while_idle?如果包含这个值?
- ?????????*?表示不会在设备处于闲置状态的时候就立即发送推送消息?
- ?????????*?服务器会等待设备变为活动状态的时候发送?
- ?????????*?并且只有collapse_key标识的最后一条信息才会被发送?**/??
- ????????if?(delay_while_idle)??
- ????????????phsb.append("&delay_while_idle=0");??
- ????????return?phsb.toString();??
- ????}??
- ??
- ????public?static?void?sendPushMessage(final?String?url,?final?String?params,?final?String?auth)?{??
- ????????try?{??
- ????????????byte[]?postData?=?params.getBytes();??
- ??????????????
- ????????????URL?requestUrl?=?new?URL(url);??
- ????????????HttpURLConnection?connection?=?(HttpURLConnection)?requestUrl.openConnection();??
- ????????????//?上传数据,需要将setDoOutput方法的参数值设为true??
- ????????????connection.setDoOutput(true);??
- ????????????//?Post请求不能使用缓存??
- ????????????connection.setUseCaches(false);??
- ????????????connection.setRequestMethod("POST");??
- ????????????connection.setRequestProperty("Content-Type",?"application/x-www-form-urlencoded");??
- ????????????connection.setRequestProperty("Content-Length",?Integer.toString(postData.length));??
- ????????????connection.setRequestProperty("Charset",?"UTF-8");??
- ????????????connection.setRequestProperty("Authorization",?"GoogleLogin?auth="?+?auth);??
- ????????????OutputStream?out?=?connection.getOutputStream();??
- ????????????out.write(postData);??
- ????????????out.flush();??
- ????????????out.close();??
- ??
- ????????????int?responseCode?=?connection.getResponseCode();??
- ????????????if?(responseCode?==?200)?{??
- ????????????????BufferedReader?br?=?new?BufferedReader(new?InputStreamReader(??
- ????????????????????????connection.getInputStream()));??
- ????????????????String?responseLine;??
- ????????????????StringBuilder?sb?=?new?StringBuilder();??
- ????????????????while?((responseLine?=?br.readLine())?!=?null)?{??
- ????????????????????sb.append(responseLine);??
- ????????????????}??
- ????????????????if?(sb.toString().startsWith("id="))?{??
- ????????????????????System.out.println("推送信息发送成功!");??
- ????????????????}??
- ????????????}?else?if?(responseCode?==?503)?{??
- ????????????????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.");??
- ????????????}?else?if?(responseCode?==?401)?{??
- ????????????????System.out.println("Indicates?that?the?ClientLogin?AUTH_TOKEN?used?to?validate?the?sender?is?invalid.");??
- ????????????}??
- ????????}?catch?(Exception?e)?{??
- ????????????e.printStackTrace();??
- ????????}??
- ????}??
- }??
?
?
1 楼 William_Duan 2011-10-11 这种方式在国内能用吗?感觉被限制了。 2 楼 pgy20032000 2011-10-11 William_Duan 写道这种方式在国内能用吗?感觉被限制了。我还没来得及试 这是从一个朋友那转的 3 楼 wulingbo2005 2012-01-11 为什么现在注册收不到广播??