谷歌云消息注册身份验证失败

13

我想尝试使用 Google Cloud Messaging (GCM) 服务,但一开始就遇到了问题。

我在尝试向 GCM 注册设备时收到了错误消息 AUTHENTICATION_FAILED。我进行了搜索,所有找到的答案都是密码错误的变体。我的密码是正确的,而且我只使用一个帐户。

在 Android 上实现 GCM 客户端有两种方法:

  1. 使用附加 JAR 的 GCM 库,现已过时。
  2. 使用 Google Play 服务 API

当然,我从第二种方法开始尝试,并遇到了这个问题。

我以为问题出在我的手机上,但后来决定尝试第一种方式,结果它起作用了!不过,这种方式已经过时,需要使用一个额外的 JAR,感觉不太对劲。

为了理解错误的原因,我反编译了 Google Play Services 的 JAR 文件并将其与 GCM 库进行了比较。

结果发现它们都有一个类似的方法,大致如下:

void register(Context context, String senderIds) {
    Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
    intent.setPackage("com.google.android.gms"); // this one row are different
    setPackageNameExtra(context, intent);
    intent.putExtra("sender", senderIds);
    context.startService(intent);
}

一行代码的区别:

在GCM库中,它是com.google.android.gsf,其中gsf代表Google服务框架(我猜),并且它可以正常工作!

在Google Play服务API jar中,它是com.google.android.gms,但它不起作用(出现了AUTHENTICATION_FAILED错误)。

然后在GCM库中,我将"gsf"替换为"gms"并运行。结果我得到了同样的AUTHENTICATION_FAILED错误!如果我输入另一个包名,则它仍然无法正常工作。

我需要做什么才能使它工作?我应该在手机上设置什么吗?还是这是Google Play服务的错误?有人遇到过这样的问题吗?

谢谢!

3个回答

2

我遇到了同样的问题,看起来谷歌并没有急于解决它。

我不想在我的应用程序中添加已弃用的客户端助手gcm.jar,所以我编写了一个最小的解决方案,在我的Android 2.3.6 Nexus One手机上运行良好,可以解决上述问题中的注册失败。

            try {
                gcm = GoogleCloudMessaging.getInstance(context);
                regID = gcm.register(SENDER_ID);
                storeRegistrationId(regID);
                msg = "Device registered, registration ID=" + regID;

                sendRegistrationIdToBackend();
            } catch (IOException ex) {
                msg = "Exception registering for GCM :" + ex.getMessage();
                // If there is an error, don't just keep trying to register.
                oldSchoolRegister();
            }

AUTHENTICATION_FAILED 触发了上述代码中的 IOException。
private void oldSchoolRegister() {
    Intent intent = new Intent("com.google.android.c2dm.intent.REGISTER");
    intent.setPackage("com.google.android.gsf");
    setRegCallbackIntent(context, intent);
    intent.putExtra("sender", SENDER_ID);
    context.startService(intent);
}

private static synchronized void setRegCallbackIntent(Context context, Intent intent) {
    regCallback = PendingIntent.getBroadcast(context, 0, new Intent(), 0);
    intent.putExtra("app", regCallback);
}

public static synchronized void cancelRegCallbackIntent() {
    if (regCallback != null) {
        regCallback.cancel();
        regCallback = null;
    }
}

我将上述代码添加到了我的应用程序中。这些是来自Client Helper gcm.jar的简化方法(所以您不需要将该jar文件添加到您的应用程序中)。

protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();

    if (extras != null && !extras.isEmpty()) {  // has effect of unparcelling Bundle
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType(intent);

        if (messageType != null) {
            if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                showMessage(extras.getString("message")); // call your code
                Logger.d(TAG, "Received message: " + message.alert + ": " + message.url);
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
                Logger.e(TAG, "Send error: " + extras.toString());
            } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
                Logger.e(TAG, "Deleted messages on server: " + extras.toString());
            }
        } else {
            String regID = extras.getString("registration_id");
            if (regID != null && !regID.isEmpty()) {
                doRegistration(regID); // send to your server etc.
                GCMSetup.storeRegistrationId(regID);
                GCMSetup.cancelRegCallbackIntent();
            }
        }
    }
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    GCMBroadcastReceiver.completeWakefulIntent(intent);
}

这段代码位于意图服务中,只有几行用于存储从GCM接收到的ID。与基本实现相比,你可以看到只增加了大约20行额外的代码,而且没有额外的依赖!你只需要更新你的AndroidManifest.xml文件以确保你能够接收REGISTRATION意图。

    <receiver android:name="com.camiolog.android.GCMBroadcastReceiver"
        android:permission="com.google.android.c2dm.permission.SEND" >
        <intent-filter>
            <action android:name="com.google.android.c2dm.intent.RECEIVE" />
            <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
            <category android:name="com.camiolog.android"/>
        </intent-filter>
    </receiver>

我希望这可以在谷歌整顿之前帮到您!

不确定我是否理解清除regcallback Pendingintent的必要性,因为此意图似乎没有任何作用,而且我没有看到您如何能够从接收REGISTRATION意图的广播接收器中调用该例程? regCallback是静态类变量吗?想知道是否可以只创建它,传递它,然后立即取消它,或者根本不在意图中包含额外内容。您知道com.google.android.gsf包是否需要“app”额外内容吗? - guyland123

1

看起来避免这个问题的解决方案是在FROYO和GINGERBREAD上发生AUTHENTICATION_FAILED错误时回退到旧的弃用GCM客户端库。

这是一个简单的代码片段,展示了如何将新的Gcm客户端升级为使用旧的客户端:

@Override
protected void onPostExecute(Integer resultCode) {

    if(resultCode == EXCEPTION_THROWED) {

        //Android 2.2 gmc bug https://dev59.com/92Ik5IYBdhLWcg3wbtyb

        //fall back to old deprecated GCM client library

        GCMRegistrar.checkDevice(StartActivity.this);
        GCMRegistrar.checkManifest(StartActivity.this);
        final String registrationId = GCMRegistrar.getRegistrationId(StartActivity.this);
        if (registrationId.equals("")) {
            GCMRegistrar.register(StartActivity.this, SENDER_ID);
        }

        //Toast.makeText(context, "Orders and menus won't be sync with other devices since GoogleCloudMessaging is not working correctly on this device. Please notify the developer.", Toast.LENGTH_LONG).show();

    }

}

您可以在此处找到旧版弃用的GCM客户端帮助程序:http://developer.android.com/google/gcm/helper.html

您可以在计算机上的以下路径中找到GCM客户端代码:ANDROID_SDK_ROOT/extras/google/gcm-client(假设您使用Android SDK Manager下载了此额外内容)。

我将旧的GCM客户端放入一个名为com.google.android.gcm.deprecated的新包中,以便提醒自己不要将其用于其他事情。


1
这似乎是一个错误。以下是一位 Android 开发人员在 android-gcm Google Group 中对此的说法:
一些背景:Froyo和Gingerbread注册是在GoogleServicesFramework中实现的,使用Google账户进行注册。这导致了许多人出现认证错误,因为账户状态不佳。
从ICS开始,GCM不依赖或使用Google账户 - 您可以在添加帐户之前或没有任何帐户的情况下使用它。
“Play服务”更新正在所有设备上实施新方案 - 但似乎有少量设备存在问题,我们正在调查 - 但数字远低于旧方案的数字。
如果您想在Froyo和Gingerbread中使用GSF中的代码 - 您需要使用先前的库,该库明确设置包名称。 GCM中的新库正在使用新的注册代码。
与Google的实际连接遵循相同的路径 - 我们正在逐步(而缓慢地)将设备移动到play服务中的新代码。
到目前为止,我有2个bug报告,并且我们有几个嫌疑人。我们知道,如果设备未连接超过9个月,则会处于此状态,并且需要进行出厂设置。
我们有一些报告,其中出厂设置无法解决问题 - 但我没有bug报告或信息来确认或跟踪此问题。唯一我确定出厂设置无法帮助的情况是,如果手机在初始签入时向服务器发送错误信息 - 我们正在为此添加额外的检查。
显然,恢复出厂设置可能会解决问题,但他们仍在调查中。

谢谢,我不想进行工厂重置。我会在另一个设备上检查它。并且在情况澄清之前,我将继续使用旧库,或者两者都用。 - user2862139

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接