Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribing topics with Google Cloud Messenger token, Invalid argument received

I am following the example that google provides to register the gcm token: https://developers.google.com/cloud-messaging/android/start

I have generated correctly the google-services.json file and I am able to receive the push tokens. But when I am trying to subscribe to any topic with the follow code:

    // Register the user to the global topic. This will help the device to be register on GCM
    GcmPubSub pubSub = GcmPubSub.getInstance(this);
    pubSub.subscribe(token, "/topics/global", null);

It throws the INVALID_ARGUMENT exception:

01-05 14:05:24.435 D/RegIntentService( 4330): java.io.IOException: INVALID_PARAMETERS
01-05 14:05:24.435 D/RegIntentService( 4330):   at com.google.android.gms.iid.zzc.zzb(Unknown Source)
01-05 14:05:24.435 D/RegIntentService( 4330):   at com.google.android.gms.iid.zzc.zza(Unknown Source)
01-05 14:05:24.435 D/RegIntentService( 4330):   at com.google.android.gms.iid.InstanceID.zzc(Unknown Source)
01-05 14:05:24.435 D/RegIntentService( 4330):   at com.google.android.gms.iid.InstanceID.getToken(Unknown Source)
01-05 14:05:24.435 D/RegIntentService( 4330):   at com.google.android.gms.gcm.GcmPubSub.subscribe(Unknown Source)
01-05 14:05:24.435 D/RegIntentService( 4330):   at gcm.play.android.samples.com.gcmquickstart.RegistrationIntentService.subscribeTopics(RegistrationIntentService.java:105)
01-05 14:05:24.435 D/RegIntentService( 4330):   at gcm.play.android.samples.com.gcmquickstart.RegistrationIntentService.onHandleIntent(RegistrationIntentService.java:65)
01-05 14:05:24.435 D/RegIntentService( 4330):   at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
01-05 14:05:24.435 D/RegIntentService( 4330):   at android.os.Handler.dispatchMessage(Handler.java:99)
01-05 14:05:24.435 D/RegIntentService( 4330):   at android.os.Looper.loop(Looper.java:137)
01-05 14:05:24.435 D/RegIntentService( 4330):   at android.os.HandlerThread.run(HandlerThread.java:60)

This is an example of push tokens that I receives:

e3r6xnFGK3E:APA91bG9oY0A7QCf86BXXh8ADzycct5QJUONTXMH3pApCkcwty0A6UXo6zLLx3Hl3ubMgBY65ldxuZzSF20nahZAq-4SiUMRS0YYStJtldK85lzrO-xM5KvM_Jigpaka-RN5TLb8D1Op

I have checked the documentation about subscribe a topic but there is nothing that says why I am receiving INVALID_PARAMETER exception:

https://developers.google.com/android/reference/com/google/android/gms/gcm/GcmPubSub.html#subscribe(java.lang.String, java.lang.String, android.os.Bundle)

Any help is appreciated.

P.d. There is the complete source code to register the tokens:

import android.annotation.SuppressLint;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.util.Log;

import com.google.android.gms.gcm.GcmPubSub;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;


/**
 * Intent service used to retrieve and save the registration token needed
 * Extracted from here
 * https://github.com/googlesamples/google-services/blob/master/android/gcm/app/src/main/java/gcm/play/android/samples/com/gcmquickstart/RegistrationIntentService.java
 */
public class RegistrationIntentService extends IntentService {

    public static final String TAG = "RegistrationIntentService";
    public static final String INTENT_KEY_UPDATE_SERVER_TOKEN_CALLBACK =
            "services.RegistrationIntentService.INTENT_KEY_UPDATE_SERVER_TOKEN_CALLBACK";

    private ResultReceiver mResultReceiver;
    public static final String BUNDLE_KEY_GCM_TOKEN =
            "services.RegistrationIntentService.BUNDLE_KEY_GCM_TOKEN";

    public RegistrationIntentService() {
        super(TAG);
    }

    @SuppressLint("LongLogTag")
    @Override
    protected void onHandleIntent(Intent intent) {
        // Get the result receiver
        Bundle extras = intent.getExtras();
        if (extras != null && extras.containsKey(INTENT_KEY_UPDATE_SERVER_TOKEN_CALLBACK)) {
            mResultReceiver = (ResultReceiver)extras.get(INTENT_KEY_UPDATE_SERVER_TOKEN_CALLBACK);
        }

        try {
            InstanceID instanceId = InstanceID.getInstance(this);
            String token = instanceId.getToken(getString(R.string.gcm_defaultSenderId),
                    GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
            Log.i(TAG, "GCM Registration Token: " + token);

            // TODO: Send registration token to the server
            if (mResultReceiver != null) {
                Bundle bundle = new Bundle();
                bundle.putString(BUNDLE_KEY_GCM_TOKEN, token);
                mResultReceiver.send(0, bundle);
            }

            // Register the user to the global topic. This will help the device to be register on GCM
            GcmPubSub pubSub = GcmPubSub.getInstance(this);
            pubSub.subscribe(token, "/topics/global", null);
            Logger.v(TAG, "User correctly register to the global token");

        } catch (Exception e) {
            Log.d(TAG, "Faield to complete token refresh", e);
        }
    }
}

And this is the content of the google-services.json

{
  "project_info": {
    "project_id": "NOT_SHOWN-aa10f",
    "project_number": "11046079110",
    "name": "NOT_SHOWN"
  },
  "client": [
    {
      "client_info": {
        "mobilesdk_app_id": "1:11046079110:android:b918cc51ed907631",
        "client_id": "android:NOT_SHOWN",
        "client_type": 1,
        "android_client_info": {
          "package_name": "NOT_SHOWN"
        }
      },
      "oauth_client": [],
      "api_key": [],
      "services": {
        "analytics_service": {
          "status": 1
        },
        "cloud_messaging_service": {
          "status": 2,
          "apns_config": []
        },
        "appinvite_service": {
          "status": 1,
          "other_platform_oauth_client": []
        },
        "google_signin_service": {
          "status": 1
        },
        "ads_service": {
          "status": 1
        }
      }
    }
  ],
  "client_info": [],
  "ARTIFACT_VERSION": "1"
}
like image 595
jiahao Avatar asked Jan 05 '16 11:01

jiahao


People also ask

What happens if a subscriber can't acknowledge a message?

If a subscriber can't acknowledge a message, Pub/Sub can forward the message to a dead-letter topic. For more information, see Forwarding to dead-letter topics. If you set a dead-letter topic, you can't enable message ordering. If you set a dead-letter topic, you can also specify the maximum number of delivery attempts.

How do I publish messages with the GCloud API?

You can publish messages with the gcloud command-line tool or the Pub/Sub API. The client libraries can asynchronously publish messages. In the Cloud Console, go to the Pub/Sub topics page. Click the topic ID. In the Topic details page, click Publish messages. In the Message body field, enter the message data.

What happened to Google Cloud Messaging?

Google Cloud Messaging, deprecated April 10 2018, has been deactivated and removed from Google's APIs. For equivalent functionality, use Firebase Cloud Messaging (FCM), which inherits the reliable and scalable GCM infrastructure, plus many new features.

How to publish messages asynchronously in the cloud console?

The client libraries can asynchronously publish messages. In the Cloud Console, go to the Pub/Sub topics page. Click the topic ID. In the Topic details page under Messages, click Publish message.


Video Answer


1 Answers

It seems that none has solve this problem so far, so I am going to give the solution that I found.

The problem was we have several process which register the GCM. So what happens in 60% of the cases is that after we register our own device, in the same app, the another process register on GCM with its own sender. Thus when we were trying to subscribe to a topic, the gcm token is not valid because the same device, the same app has register the gcm for another sender.

To solve the problem, what we have done is get the sender id from the another process, then attach it to our sender.

Let's say our sender id is "1234567", and his sender id is "7654321", so when we register our app on GCM, instead of parsing only "1234567", we use "1234567,7654321", separated by coma.

This allow us to obtain a GCM token that is valid both for us and for the another process, while if the another process register the GCM after us, it won't invalidate own GCM token. (His GCM token will still be valid because we include its sender as part of the request).

Cheers from Dubai!

like image 65
jiahao Avatar answered Oct 19 '22 12:10

jiahao