13

Google Cloud Messaging (GCM) サービスを試してみたいのですが、最初は問題に直面しています。

AUTHENTICATION_FAILEDデバイスを GCM に登録しようとすると、エラーが発生します。検索したところ、間違ったパスワードのバリエーションしか見つかりませんでした。パスワードは正しく、使用しているアカウントは 1 つだけです。

Android に GCM クライアントを実装するには、次の 2 つの方法があります。

  1. 追加の jar を含む GCM ライブラリ。現在は非推奨です。
  2. Google Play Services API

もちろん2番目から始めて、この問題に遭遇しました。

問題は私の電話にあると思いましたが、最初の方法を試すことにしました。ただし、これは推奨されておらず、追加の 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);
}

1行の違い:

GCM ライブラリではcom.google.android.gsfgsfGoogle Services Framework はどこにあるのでしょうか (私は推測します)、それは機能します!

Google Play Services API jar ではcom.google.android.gms、動作しません (AUTHENTICATION_FAILED エラー)。

次に、GCM ライブラリで「gsf」を「gms」に置き換えて実行しました。そして、同じ AUTHENTICATION_FAILED エラーが発生しました! 別のパッケージに入ると、機能しません。

それを機能させるために何をする必要がありますか? 電話で何かを設定する必要がありますか?それとも、Google Play Services のバグですか? 誰かがそのような問題に遭遇しましたか?

前もって感謝します!

4

3 に答える 3

2

私は同じ問題に遭遇しました.Googleが急いで修正しているようには見えません.

非推奨のクライアント ヘルパー 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;
    }
}

上記のコードをアプリに追加しました。これらはクライアント ヘルパー 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>

グーグルが彼らの行動をまとめるまで、これが役立つことを願っています!

于 2014-01-16T01:03:12.120 に答える
1

したがって、この問題を回避する解決策は、FROYO と GINGERBREAD で AUTHENTICATION_FAILED エラーが発生した場合に備えて、古い非推奨の GCM クライアント ライブラリにフォールバックすることのようです。

以下は、古いクライアントを使用するために新しい Gcm クライアントをフォールバックにアップグレードする方法の簡単なコード スニペットです。

@Override
protected void onPostExecute(Integer resultCode) {

    if(resultCode == EXCEPTION_THROWED) {

        //Android 2.2 gmc bug http://stackoverflow.com/questions/19269607/google-cloud-messaging-register-authentication-failed

        //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 という名前の新しいパッケージに入れて、これを他のものに使用しないように自分自身を思い出そうとしました。

于 2013-10-29T12:51:28.147 に答える
1

これはバグのようです。Android 開発者がandroid-gcm Google Groupでそれについて言っていることは次のとおりです。

背景: Froyo と Gingerbread の登録は、登録に Google アカウントを使用して GoogleServicesFramework に実装されています。これにより、アカウントが良好な状態でない場合に多くの認証エラーが発生しました。

ICS 以降、GCM は Google アカウントに依存したり使用したりしません。アカウントを追加する前に、またはアカウントなしで使用できます。

「Play サービス」の更新により、すべてのデバイスで新しいスキームが実装されます。ただし、少数のデバイスで問題が発生しているようで、調査中です。ただし、その数は古いスキームのデバイスよりもはるかに少なくなっています。

Froyo と Gingerbread の GSF でコードを使用する場合は、パッケージ名を明示的に設定する以前のライブラリを使用する必要があります。 GCM の新しいライブラリは、新しい登録コードを使用しています。

Google への実際の接続は同じパスをたどっています。デバイスをプレイ サービスの新しいコードに徐々に (そしてゆっくりと) 移行しています。

これまでに 2 件のバグレポートがあり、いくつかの疑いがあります。デバイスが 9 か月以上接続されていない場合、この状態になり、出荷時設定へのリセットが必要になることがわかっています。

工場出荷時設定にリセットしても問題が解決しないという報告がいくつかありましたが、これを確認または追跡するためのバグレポートや情報はありません。工場出荷時設定へのリセットが役に立たない唯一のケースは、電話が最初のチェックインでサーバーに不適切な情報を送信している場合です。これについては、追加のチェックを追加しています.

どうやら、工場出荷時の状態にリセットすると問題が解決する可能性がありますが、まだ調査中です。

于 2013-10-09T20:30:08.347 に答える