使用Google Cloud Messenger令牌订阅主题,收到无效的参数

我正在按照google提供的示例注册gcm令牌: https : //developers.google.com/cloud-messaging/android/start

我已经正确生成了google-services.json文件,并且能够接收推送令牌。 但是当我试图用下面的代码来订阅任何主题时:

// 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); 

它引发INVALID_ARGUMENTexception:

 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) 

这是我收到的推送令牌的一个例子:

 e3r6xnFGK3E:APA91bG9oY0A7QCf86BXXh8ADzycct5QJUONTXMH3pApCkcwty0A6UXo6zLLx3Hl3ubMgBY65ldxuZzSF20nahZAq-4SiUMRS0YYStJtldK85lzrO-xM5KvM_Jigpaka-RN5TLb8D1Op 

我已经检查了有关订阅主题的文档,但没有说明为什么我收到INVALID_PARAMETERexception:

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

任何帮助表示赞赏。

Pd有注册令牌的完整源代码:

 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); } } } 

这是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" } 

Solutions Collecting From Web of "使用Google Cloud Messenger令牌订阅主题,收到无效的参数"

看来目前还没有人解决这个问题,所以我要给我find的解决scheme。

问题是我们有几个注册GCM的过程。 那么在60%的情况下会发生什么呢?在我们注册了自己的设备之后,在同一个应用程序中,另一个进程在GCM上注册了它自己的发件人。 因此,当我们尝试订阅某个主题时,gcm令牌无效,因为同一个设备,同一个应用程序已经为另一个发件人注册gcm。

为了解决这个问题,我们所做的是从另一个进程获取发件人ID,然后将其附加到我们的发件人。

假设我们的发件人ID是“1234567”,他的发件人ID是“7654321”,所以当我们在GCM上注册我们的应用程序时,我们使用“1234567,7654321”而不是仅parsing“1234567”,以昏迷分隔。

这使我们能够获得一个对我们和另一个进程都有效的GCM令牌,而如果另一个进程在我们之后注册GCM,它将不会使自己的GCM令牌失效。 (他的GCM令牌仍然有效,因为我们包含发件人作为请求的一部分)。

来自迪拜的欢呼!