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

Android 使用Google Cloud Messenger令牌订阅主题,收到无效参数,android,google-cloud-messaging,Android,Google Cloud Messaging,我遵循google提供的注册gcm令牌的示例: 我已经正确生成了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.subscr

我遵循google提供的注册gcm令牌的示例:

我已经正确生成了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);
它抛出无效的_参数异常:

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
我已经查看了有关订阅主题的文档,但没有说明我收到无效\u参数异常的原因:

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)

感谢您的帮助

p.d.有完整的源代码来注册令牌:

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

似乎到目前为止还没有人能解决这个问题,所以我将给出我找到的解决方案

问题是我们有几个进程来注册GCM。因此,在60%的情况下,当我们在同一个应用程序中注册自己的设备后,另一个进程在GCM上向自己的发送者注册。因此,当我们尝试订阅主题时,gcm令牌无效,因为同一设备、同一应用程序已为另一个发送者注册了gcm

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

假设我们的发送者id是“1234567”,他的发送者id是“7654321”,所以当我们在GCM上注册我们的应用程序时,我们使用“12345677654321”,而不是只解析“1234567”,由coma分隔

这允许我们获得对我们和另一个进程都有效的GCM令牌,而如果另一个进程在我们之后注册GCM,它不会使自己的GCM令牌无效。(他的GCM令牌仍然有效,因为我们将其发送者包括在请求中)


来自迪拜的干杯

我认为问题在于在获取实例时使用
this
。更改InstanceID InstanceID=InstanceID.getInstance(此)to
InstanceID InstanceID=InstanceID.getInstance(getApplicationContext())
GcmPubSub pubSub=GcmPubSub.getInstance(此)
to
GcmPubSub pubSub=GcmPubSub.getInstance(getApplicationContext())以确保它们在相同的上下文中。您好:谢谢您的回复。我认为这不是问题所在。该代码在近40%的时间内有效。因此,在代码运行时应该有一些条件更改。RegistrationEntService从IntentService扩展而来,IntentService从Service扩展而来,后者从ContextWrapper扩展而来,ContextWrapper从上下文本身扩展而来。这不应该是问题,我明白了。您是否检查了您正在使用的令牌,或者您正在使用gcm.register()获取令牌,这些可能是导致问题的原因。否。正如你所看到的,事实并非如此。我对这个答案很感兴趣,但是你如何“从另一个进程获取发送者id,然后将其附加到我们的发送者。”?我已经花了一段时间研究它。我不确定答案是否正确。发件人id是您在清单中拥有的。我想就加在那里吧。