Chromium Code Reviews| Index: components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java |
| diff --git a/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java |
| index d8a825340212511f064fb62e66500636bc976073..4366b04d4eea2f6ea8e3ee823c372d30abd4a576 100644 |
| --- a/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java |
| +++ b/components/gcm_driver/android/java/src/org/chromium/components/gcm_driver/GoogleCloudMessagingV2.java |
| @@ -19,29 +19,25 @@ |
| /** |
| - * Temporary code for sending subtypes when (un)registering with GCM. |
| + * Temporary code for sending subtypes when (un)subscribing with GCM. |
| * Subtypes are experimental and may change without notice! |
| * TODO(johnme): Remove this file, once we switch to the GMS client library. |
| */ |
| public class GoogleCloudMessagingV2 { |
| - // Inlined com.google.android.gms.common.GooglePlayServicesUtil.GOOGLE_PLAY_SERVICES_PACKAGE |
| - // since this class mustn't depend on the GMS client library. |
| private static final String GOOGLE_PLAY_SERVICES_PACKAGE = "com.google.android.gms"; |
| private static final long REGISTER_TIMEOUT = 5000; |
| - private static final String ACTION_C2DM_REGISTER = |
| - "com.google.android.c2dm.intent.REGISTER"; |
| - private static final String ACTION_C2DM_UNREGISTER = |
| - "com.google.android.c2dm.intent.UNREGISTER"; |
| + private static final String ACTION_C2DM_REGISTER = "com.google.android.c2dm.intent.REGISTER"; |
| private static final String C2DM_EXTRA_ERROR = "error"; |
| private static final String INTENT_PARAM_APP = "app"; |
| private static final String ERROR_MAIN_THREAD = "MAIN_THREAD"; |
| private static final String ERROR_SERVICE_NOT_AVAILABLE = "SERVICE_NOT_AVAILABLE"; |
| + private static final String EXTRA_DELETE = "delete"; |
| private static final String EXTRA_REGISTRATION_ID = "registration_id"; |
| - private static final String EXTRA_UNREGISTERED = "unregistered"; |
| private static final String EXTRA_SENDER = "sender"; |
| private static final String EXTRA_MESSENGER = "google.messenger"; |
| private static final String EXTRA_SUBTYPE = "subtype"; |
| + private static final String EXTRA_SUBSCRIPTION = "subscription"; |
| private Context mContext; |
| private PendingIntent mAppPendingIntent = null; |
| @@ -51,80 +47,131 @@ public GoogleCloudMessagingV2(Context context) { |
| mContext = context; |
| } |
| + public String subscribe(String source, String subtype, Bundle data) throws IOException { |
| + if (data == null) { |
| + data = new Bundle(); |
| + } |
| + data.putString(EXTRA_SUBTYPE, subtype); |
| + Bundle result = subscribe(source, data); |
| + return result.getStringExtra(EXTRA_REGISTRATION_ID); |
| + } |
| + |
| + public String unsubscribe(String source, String subtype, Bundle data) throws IOException { |
| + if (data == null) { |
| + data = new Bundle(); |
| + } |
| + data.putString(EXTRA_SUBTYPE, subtype); |
| + return unsubscribe(source, data); |
| + } |
| + |
| /** |
| - * Register the application for GCM and return the registration ID. You must call this once, |
| - * when your application is installed, and send the returned registration ID to the server. |
| - * <p> |
| - * This is a blocking call—you shouldn't call it from the UI thread. |
| - * <p> |
| - * Repeated calls to this method will return the original registration ID. |
| + * Subscribe to receive GCM messages from a specific source. |
| * <p> |
| - * If you want to modify the list of senders, you must call {@code unregister()} first. |
| + * Source Types: |
| + * <ul> |
| + * <li>Sender ID - if you have multiple senders you can call this method |
| + * for each additional sender. Each sender can use the corresponding |
| + * {@link #REGISTRATION_ID} returned in the bundle to send messages |
| + * from the server.</li> |
| + * <li>Cloud Pub/Sub topic - You can subscribe to a topic and receive |
| + * notifications from the owner of that topic, when something changes. |
| + * For more information see |
| + * <a href="https://cloud.google.com/pubsub">Cloud Pub/Sub</a>.</li> |
| + * </ul> |
| + * This function is blocking and should not be called on the main thread. |
| + * |
| + * @param source of the desired notifications. |
| + * @param data (optional) additional information. |
| + * @return Bundle containing subscription information including {@link #REGISTRATION_ID} |
| + * @throws IOException if the request fails. |
| + */ |
| + public Bundle subscribe(String source, Bundle data) throws IOException { |
| + if (data == null) { |
| + data = new Bundle(); |
| + } |
| + // Expected by older versions of GMS and servlet |
| + data.putString(EXTRA_SENDER, source); |
| + // New name of the sender parameter |
| + data.putString(EXTRA_SUBSCRIPTION, source); |
| + // DB buster for older versions of GCM. |
| + if (data.getString(EXTRA_SUBTYPE) == null) { |
| + data.putString(EXTRA_SUBTYPE, source); |
| + } |
| + |
| + Intent resultIntent = registerRpc(data); |
| + getExtraOrThrow(resultIntent, EXTRA_REGISTRATION_ID); |
| + return resultIntent.getExtras(); |
| + } |
| + |
| + /** |
| + * Unsubscribe from a source to stop receiving messages from it. |
| * <p> |
| - * Most applications use a single sender ID. You may use multiple senders if different |
| - * servers may send messages to the app or for testing. |
| + * This function is blocking and should not be called on the main thread. |
| * |
| - * @param senderIds list of project numbers or Google accounts identifying who is allowed to |
| - * send messages to this application. |
| - * @return registration id |
| + * @param source to unsubscribe |
| + * @param data (optional) additional information. |
| + * @throws IOException if the request fails. |
| */ |
| - public String register(String subtype, String... senderIds) throws IOException { |
| + public void unsubscribe(String source, Bundle data) throws IOException { |
| + if (data == null) { |
| + data = new Bundle(); |
| + } |
| + // Use the register servlet, with 'delete=true' |
|
jianli
2015/02/12 20:03:30
nit: end with period
johnme
2015/02/13 19:11:56
Done.
|
| + // Registration service returns a registration_id on success - or an error code |
|
jianli
2015/02/12 20:03:30
ditto
johnme
2015/02/13 19:11:56
Done.
|
| + data.putString(EXTRA_DELETE, "1"); |
| + subscribe(source, data); |
| + } |
| + |
| + private void registerRpc(Bundle data) { |
| if (Looper.getMainLooper() == Looper.myLooper()) { |
| throw new IOException(ERROR_MAIN_THREAD); |
| } |
| + if (getGcmVersion() < 0) { |
| + throw new IOException("Google Play Services missing"); |
| + } |
| + if (data == null) { |
| + data = new Bundle(); |
| + } |
| - final BlockingQueue<Intent> registerResult = new LinkedBlockingQueue<Intent>(); |
| - Handler registrationHandler = new Handler(Looper.getMainLooper()) { |
| + final BlockingQueue<Intent> responseResult = new LinkedBlockingQueue<Intent>(); |
| + Handler responseHandler = new Handler(Looper.getMainLooper()) { |
| @Override |
| public void handleMessage(Message msg) { |
| Intent res = (Intent) msg.obj; |
| - registerResult.add(res); |
| + responseResult.add(res); |
| } |
| }; |
| - Messenger messenger = new Messenger(registrationHandler); |
| - |
| - internalRegister(messenger, subtype, senderIds); |
| + Messenger responseMessenger = new Messenger(responseHandler); |
| + Intent intent = new Intent(ACTION_C2DM_REGISTER); |
| + intent.setPackage(GOOGLE_PLAY_SERVICES_PACKAGE); |
| + setPackageNameExtra(intent); |
| + intent.putExtras(data); |
| + intent.putExtra(EXTRA_MESSENGER, responseMessenger); |
| + mContext.startService(intent); |
| try { |
| - Intent regIntent = registerResult.poll(REGISTER_TIMEOUT, TimeUnit.MILLISECONDS); |
| - if (regIntent == null) { |
| - throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| - } |
| - String registrationId = regIntent.getStringExtra(EXTRA_REGISTRATION_ID); |
| - // registration succeeded |
| - if (registrationId != null) { |
| - return registrationId; |
| - } |
| - String err = regIntent.getStringExtra(C2DM_EXTRA_ERROR); |
| - if (err != null) { |
| - throw new IOException(err); |
| - } else { |
| - throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| - } |
| + return resultIntent = responseResult.poll(REGISTER_TIMEOUT, TimeUnit.MILLISECONDS); |
| } catch (InterruptedException e) { |
| throw new IOException(e.getMessage()); |
| } |
| } |
| - private void internalRegister(Messenger messenger, String subtype, String... senderIds) { |
| - Intent intent = new Intent(ACTION_C2DM_REGISTER); |
| - intent.setPackage(GOOGLE_PLAY_SERVICES_PACKAGE); |
| - if (subtype != null) intent.putExtra("subtype", subtype); |
| - intent.putExtra(EXTRA_MESSENGER, messenger); |
| - setPackageNameExtra(intent); |
| - intent.putExtra(EXTRA_SENDER, getFlatSenderIds(senderIds)); |
| - mContext.startService(intent); |
| - } |
| + private String getExtraOrThrow(Intent intent, String extraKey) throws IOException { |
| + if (intent == null) { |
| + throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| + } |
| - private String getFlatSenderIds(String... senderIds) { |
| - if (senderIds == null || senderIds.length == 0) { |
| - throw new IllegalArgumentException("No senderIds"); |
| + String extraValue = intent.getStringExtra(extraKey); |
| + if (extraValue != null) { |
| + return extraValue; |
| } |
| - StringBuilder builder = new StringBuilder(senderIds[0]); |
| - for (int i = 1; i < senderIds.length; i++) { |
| - builder.append(',').append(senderIds[i]); |
| + |
| + String err = intent.getStringExtra(C2DM_EXTRA_ERROR); |
| + if (err != null) { |
| + throw new IOException(err); |
| + } else { |
| + throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| } |
| - return builder.toString(); |
| } |
| private void setPackageNameExtra(Intent intent) { |
| @@ -140,63 +187,14 @@ private void setPackageNameExtra(Intent intent) { |
| intent.putExtra(INTENT_PARAM_APP, mAppPendingIntent); |
| } |
| - /** |
| - * Unregister the application. Calling {@code unregister()} stops any |
| - * messages from the server. |
| - * <p> |
| - * This is a blocking call—you shouldn't call it from the UI thread. |
| - * <p> |
| - * You should rarely (if ever) need to call this method. Not only is it |
| - * expensive in terms of resources, but it invalidates your registration ID, |
| - * which you should never change unnecessarily. A better approach is to simply |
| - * have your server stop sending messages. Only use unregister if you want |
| - * to change your sender ID. |
| - * |
| - * @throws IOException if we can't connect to server to unregister. |
| - */ |
| - public void unregister(String subtype) throws IOException { |
| - if (Looper.getMainLooper() == Looper.myLooper()) { |
| - throw new IOException(ERROR_MAIN_THREAD); |
| - } |
| - final BlockingQueue<Intent> registerResult = new LinkedBlockingQueue<Intent>(); |
| - Handler registrationHandler = new Handler(Looper.getMainLooper()) { |
| - @Override |
| - public void handleMessage(Message msg) { |
| - Intent res = (Intent) msg.obj; |
| - registerResult.add(res); |
| - } |
| - }; |
| - Messenger messenger = new Messenger(registrationHandler); |
| - internalUnregister(messenger, subtype); |
| + private int getGcmVersion() { |
| + PackageManager pm = context.getPackageManager(); |
| try { |
| - Intent regIntent = registerResult.poll(REGISTER_TIMEOUT, TimeUnit.MILLISECONDS); |
| - if (regIntent == null) { |
| - throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| - } |
| - String unregistered = regIntent.getStringExtra(EXTRA_UNREGISTERED); |
| - if (unregistered != null) { |
| - // All done |
| - return; |
| - } |
| - String err = regIntent.getStringExtra(C2DM_EXTRA_ERROR); |
| - if (err != null) { |
| - throw new IOException(err); |
| - } else { |
| - throw new IOException(ERROR_SERVICE_NOT_AVAILABLE); |
| - } |
| - } catch (InterruptedException e) { |
| - throw new IOException(e.getMessage()); |
| + PackageInfo packageInfo = pm.getPackageInfo(GOOGLE_PLAY_SERVICES_PACKAGE, 0); |
| + return packageInfo.versionCode; |
| + } catch (PackageManager.NameNotFoundException e) { |
| + // No problem |
| } |
| - } |
| - |
| - private void internalUnregister(Messenger messenger, String subtype) { |
| - Intent intent = new Intent(ACTION_C2DM_UNREGISTER); |
| - intent.setPackage(GOOGLE_PLAY_SERVICES_PACKAGE); |
| - if (subtype != null) { |
| - intent.putExtra("subtype", subtype); |
| - } |
| - intent.putExtra(EXTRA_MESSENGER, messenger); |
| - setPackageNameExtra(intent); |
| - mContext.startService(intent); |
| + return -1; |
| } |
| } |