InstanceID API 返回的 GCM 令牌给出 NotRegistered 错误

Posted

技术标签:

【中文标题】InstanceID API 返回的 GCM 令牌给出 NotRegistered 错误【英文标题】:GCM Token returned by InstanceID API gives NotRegistered error 【发布时间】:2016-04-02 15:15:24 【问题描述】:

我在我的应用程序中使用 GCM 并使用 InstanceId API 生成 GCM 令牌。我正面临InstanceId API 返回的令牌无效的问题。

我使用 Postman 来检查令牌,并且不时地在某些设备中尝试使用令牌会引发 NotRegistered 错误。虽然,如果我随后强制执行GCMInstanceIdListener 服务,它会再次调用GCMRegistrationService,这一次我得到了正确的令牌。

有没有办法检查我在GCMRegistrationService 中收到的令牌是否有效?我知道我们可以调用 https://android.googleapis.com/gcm/send 并验证令牌,但它需要在标头中传递服务器密钥,我不想将其存储在客户端上。

这就是我的代码的样子:

public class GCMInstanceIdListener extends InstanceIDListenerService 

    @Override
    public void onTokenRefresh() 
        Intent intent = new Intent(this, GCMRegistrationService.class);
        startService(intent);
    



public class GCMRegistrationService extends IntentService 
    private static final String TAG = "GCMRegistrationService";

    public GCMRegistrationService() 
        super(TAG);
    

    @Override
    protected void onHandleIntent(Intent intent) 
        InstanceID instanceID = InstanceID.getInstance(this);
        String token = instanceID.getToken(BuildConfig.GCM_SENDER_ID,
                GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
        Log.d(TAG, "GCM Token : " + token);
    

【问题讨论】:

【参考方案1】:

每次启动应用时运行GCMRegistrationService,并检查您在客户端本地保存的令牌是否与收到的令牌匹配。

@Override
protected void onHandleIntent(Intent intent) 
    String token = InstanceID.getInstance(this).getToken(BuildConfig.GCM_SENDER_ID,
            GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

    String savedToken = prefs.getString("token", "");

    if(!token.equals(savedToken)) 
        prefs.edit().putString("token", token).apply();
        sendTokenToBackend(token);    // If needed
    

编辑:另外,请确保您拥有 GET_ACCOUNTS 权限。最近,我从我的应用程序中删除了此权限,并且我的设备上出现了 NotRegistered 错误。如果您的应用针对 API 23+,您需要在运行时请求此权限。

【讨论】:

我可以这样做,但在我们的用例中,我们需要在用户第一次打开应用程序时立即向他们发送推送消息。运行GCMRegistrationService 只会从第二次开始有帮助。即使在全新安装中,当第一次调用 GCMRegistrationService 时,我也会得到一个无效的令牌。 你为什么不关注谷歌的示例 gcm 客户端。它使用本地广播来通知活动注册已完成。然后,您可以继续执行其余的逻辑。至于无效令牌,我能想到的唯一两件事是您的 google-services.json 有问题(可能是文件损坏)或者您没有 GET_ACCOUNTS 权限(可能是 Android 6.0+ 权限问题) 嗯,我会检查的。虽然我们的清单中确实有 GET_ACCOUNTS 权限,并且我已经重新复制了几次 json 文件,但它并没有解决问题。 GET_ACCOUNTS 被定义为“正常”权限,但显然需要在 API 23+ 的运行时请求,就好像它是“危险”权限一样。至少这是在我的应用中发生的情况。 是的,但我们目前在我们的应用程序中没有针对 API 23+。

以上是关于InstanceID API 返回的 GCM 令牌给出 NotRegistered 错误的主要内容,如果未能解决你的问题,请参考以下文章

Android GCM InstanceId.getToken() -> java.io.IOException: TIMEOUT

识别上游 GCM 消息的发送者

为啥 InstanceID 总是返回一个令牌,尽管有错误的 senderId?

Android APP 从 GCM 迁移到 FCM。旧 GCM 令牌不起作用

无法在 API 级别 17 上获取令牌

Android GCM 示例 - 如何在现有项目中实现?