web-dev-qa-db-ja.com

Googleクラウドメッセージング登録エラーを修正する方法:SERVICE_NOT_AVAILABLE?

私は奇妙な問題に遭遇しました-私はかなり長い間アプリケーションでGCMを使用しており、すべてが完全に機能しています。ただし、Google Playのリリース前に、アプリケーションパッケージ名を_com.Android.testapp_から_com.Android.recognition_に変更し、このGCMが機能しなくなった後。最初にエラー_GCM sender id not set on constructor_が発生し、getSenderIds(Context context)をオーバーライドして修正しましたが、登録IDを取得できなくなりました。 logcatからのメッセージは次のとおりです。 enter image description here

どうすれば修正できますか?新しいパッケージに切り替えたときに、マニフェストファイルのすべてを新しいパッケージに変更しました。

_<receiver
        Android:name="com.google.Android.gcm.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.Android.recognition" />
        </intent-filter>
    </receiver>
_

それで、この背後にある問題は何ですか?アプリケーションパッケージの名前を変更するとこれが発生する可能性がありますか、それとも別の理由がありますか?

25

この_SERVICE_NOT_AVAILABLE_エラーは、_GCM Service_が現在使用できないことを示しています。しばらく待ってから試してください。

これは(私の経験として)何度も発生するので、心配する必要はありません。


GCM LibのGCMConstantsクラスを参照してください。

_/**
     * The device can't read the response, or there was a 500/503 from the
     * server that can be retried later. The application should use exponential
     * back off and retry.
     */
    public static final String ERROR_SERVICE_NOT_AVAILABLE =
            "SERVICE_NOT_AVAILABLE";
_

詳細な調査については、GCMBaseIntentServicehandleRegistration()を参照してください。

_private void handleRegistration(final Context context, Intent intent) {
        String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);
        String error = intent.getStringExtra(EXTRA_ERROR);
        String unregistered = intent.getStringExtra(EXTRA_UNREGISTERED);
        Log.d(TAG, "handleRegistration: registrationId = " + registrationId +
                ", error = " + error + ", unregistered = " + unregistered);

        // registration succeeded
        if (registrationId != null) {
            GCMRegistrar.resetBackoff(context);
            GCMRegistrar.setRegistrationId(context, registrationId);
            onRegistered(context, registrationId);
            return;
        }

        // unregistration succeeded
        if (unregistered != null) {
            // Remember we are unregistered
            GCMRegistrar.resetBackoff(context);
            String oldRegistrationId =
                    GCMRegistrar.clearRegistrationId(context);
            onUnregistered(context, oldRegistrationId);
            return;
        }

        // last operation (registration or unregistration) returned an error;
        Log.d(TAG, "Registration error: " + error);
        // Registration failed
        if (ERROR_SERVICE_NOT_AVAILABLE.equals(error)) {
            boolean retry = onRecoverableError(context, error);
            if (retry) {
                int backoffTimeMs = GCMRegistrar.getBackoff(context);
                int nextAttempt = backoffTimeMs / 2 +
                        sRandom.nextInt(backoffTimeMs);
                Log.d(TAG, "Scheduling registration retry, backoff = " +
                        nextAttempt + " (" + backoffTimeMs + ")");
                Intent retryIntent =
                        new Intent(INTENT_FROM_GCM_LIBRARY_RETRY);
                retryIntent.putExtra(EXTRA_TOKEN, TOKEN);
                PendingIntent retryPendingIntent = PendingIntent
                        .getBroadcast(context, 0, retryIntent, 0);
                AlarmManager am = (AlarmManager)
                        context.getSystemService(Context.ALARM_SERVICE);
                am.set(AlarmManager.ELAPSED_REALTIME,
                        SystemClock.elapsedRealtime() + nextAttempt,
                        retryPendingIntent);
                // Next retry should wait longer.
                if (backoffTimeMs < MAX_BACKOFF_MS) {
                  GCMRegistrar.setBackoff(context, backoffTimeMs * 2);
                }
            } else {
                Log.d(TAG, "Not retrying failed operation");
            }
        } else {
            // Unrecoverable error, notify app
            onError(context, error);
        }
    }
_
32
Pankaj Kumar

私の場合、問題はもう少し複雑でした。

  1. アクティブなインターネット接続があることを確認してください
  2. マニフェストにインターネット許可があることを確認してください
  3. Eranが述べたように、パッケージ名が正しいことを確認してください
  4. デバイスの時刻が正しく設定されています。すべてが完璧であっても、デバイスのクロックが正しく設定されていないと失敗します。

間違った時計が問題を引き起こしました。 :)

42
Aman Gautam

マニフェストの権限の部分でパッケージ名を変更したことを確認してください:

<permission Android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE"
    Android:protectionLevel="signature" />
<uses-permission Android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />

その部分のパッケージ名が正しくないため、同様のエラーが発生しました。

18
Eran

SERVICE_NOT_AVAILABLEは、Google Cloud Messagingで最もイライラする問題の1つです。これは、プッシュ通知用にデバイスを登録し、登録IDを返す関数呼び出しであるGoogleCloudMessaging.register(SENDER_ID)によってスローされる例外です。

  1. SERVICE_NOT_AVAILABLEは、ユーザーのデバイスが登録要求への応答を読み取れないか、サーバーから500/503エラーコードが返されたことを意味する場合があります。このエラーはGoogle側にあるため、開発者はこのエラーを修正する方法がありません。そのため、ユーザーが数時間後に再試行することをやみくもに提案できます。
  2. 登録が成功した場合でも、一部のデバイスでSERVICE_NOT_AVAILABLEが発生する場合があります。これは、コールが失敗したときにトークンをキャッチする回避策のブロードキャストレシーバーを実装することで修正できます。この回避策を実装し、一部のユーザーの問題を解決した可能性がありますが、それでも多くのSERVICE_NOT_AVAILABLEの苦情を受け取りました。
  3. SERVICE_NOT_AVAILABLEは、デバイス上のGoogle Play Servicesライブラリが古いか、見つからないために発生する場合があります。この場合、アプリは理論的には、それぞれのGoogle Playアプリのリストを開くことにより、Google Playサービスを更新するようユーザーに通知できます。ただし、アプリはこれがSERVICE_NOT_AVAILABLEがスローされた理由であるとは考えていないため、盲目的にユーザーをGoogle PlayのGoogle Play Servicesアプリページにリダイレクトすることはできません。
  4. SERVICE_NOT_AVAILABLEは、デバイスの時計がネットワークと同期していない場合に発生する可能性があります。繰り返しますが、開発者はこれが正確な問題であることを知る方法がないため、システムクロックの同期を確認するようユーザーに盲目的に提案できます。
  5. SERVICE_NOT_AVAILABLEは、ルート化されたユーザーがデバイスからハングアウト/ GTalkアプリを削除したときに発生する可能性があります(ブロートウェアと見なされるため)。 GCMはHangouts/GTalkによって実装および処理されるため、GCMなしでGCMを使用することはできません。
  6. ユーザーがGoogle APIがインストールされていないデバイス(Amazon Kindleなど)を実行している場合、SERVICE_NOT_AVAILABLEが発生することがあります。ここで行うことはありません。これらのユーザーはアプリからプッシュ通知を受け取ることはありません。

詳細: http://eladnava.com/google-cloud-messaging-extremely-unreliable/

これらの問題だけで、GCMの代替案を探し始めることができました。 SERVICE_NOT_AVAILABLEがスローされたときに表示されるエラーメッセージを含むコメントを付けて、アプリで1つまたは2つ星のレビューを毎日取得します。これらのユーザーを支援するために私ができることは何もありませんでした。なぜなら、彼らの大半は、彼らの制御不能の理由でそれを受け取っていたからです。

Googleクラウドメッセージングの代替

Pushy( https://pushy.me/ )は、GCMから完全に独立したスタンドアロンのプッシュ通知ゲートウェイです。プッシュ通知を受信するために、GCMと同様に独自のバックグラウンドソケット接続を維持します。基礎となるプロトコルは、ネットワーク帯域幅とバッテリーをほとんど使用しない、非常に軽量なpub/subプロトコルであるMQTTです。

Pushyの大きな利点は、(サーバーから)プッシュ通知を送信し、プッシュ通知用にデバイスを登録するためのコードが、実際にはGCMとPushyの間で交換可能であることです。これにより、GCMを実装し、不安定性のためにそれを捨てなければならない後、Pushyに切り替えるのは非常に簡単になります。

(完全開示:自分のプロジェクトのためにPushyを設立し、多くのアプリがそのようなサービスから利益を得ることに気付きました)

18
Elad Nava

私にとって-デバイスの時刻は正しくありませんでした。 「自動日付と時刻」を使用するようにデバイス設定を変更し、再試行しましたが、すべてうまくいきました。

乾杯

13
Mahendra Liya

私は同じ問題を抱えていましたが、上記の解決策のいずれも私の場合の問題を解決しませんでした。幸いなことに、私は最近それを解決したので、他の人に役立つ方法を説明したいと思います。

私の場合、Pushサービスをカスタムアプリケーションクラスに登録していました(これはアクティビティの前に実行されます。これは、何らかの理由で適切に初期化されなかったためだと思います)。メインアクティビティに変更することで問題は解決しました。

public class MyCustomApp extends Application {

    @Override
    public void onCreate() {
         super.onCreate();
         PushService.register(this); //BAD IDEA, don't register pushes in Application Class
    }

}
3
Corbella

私には接続の問題がありました。インターネット接続を変更すると問題が解決しました

3

同様の問題がありました。 google nexus(Android 4.4.2)では正常に動作しましたが、Samsung galaxy s3(Android 4.1.2)では正常に動作しました。 Samsungへの登録時にSERVICE_NOT_AVAILABLEを取得していました。それはサムスンの時間がオフになったことが判明した。 Network Timeで自動更新するように設定されていません。 GCMが魅力のように機能することを修正したら。ありがとう-ウメシュ

3
user3541251

私の場合、解決策は、 https://snowdog.co/blog/dealing-with-service_not_available-google-ごとに、マニフェストに新しいインテントフィルターアクションREGISTRATIONを追加することでしたクラウドメッセージング/

    <receiver
        Android:name=".RemoteNotificationReceiver"
        Android:permission="com.getset.getset.c2dm.permission.SEND" >
        <intent-filter>
            <action Android:name="com.getset.getset.c2dm.intent.RECEIVE" />
            <action Android:name="com.getset.getset.c2dm.intent.REGISTRATION" />
            <category Android:name="com.getset.getset" />
        </intent-filter>
    </receiver>

チュートリアルから欠落していることを考えると、これが機能することに驚いていることを認めざるを得ませんが、それを削除することは間違いなく成功した登録IDを例外に変えます。

注:Nexus 5 API 21(Lollipop)エミュレーターを使用します。

3
Brian Marick

私にとっては、Galaxy S4の[データ使用オプション]で[バックグラウンドデータを制限する]をオンにして、Googleサービスの[バックグラウンドデータアクセス]を無効にしました。セラーネットワークで問題を解決するとすぐに解決しました。 Wifiでは正常に動作していました。

3
ahmadalibaloch

私にとって問題は、電話がインターネットに接続されていないことでした。 Wi-Fiを切断して接続し、ブラウザとの接続をテストして、再度テストしました。魅力のように働いた:-)

2

私にとって、SERVICE_NOT_AVAILABLEの問題は、レシーバクラスのために私のアプリケーションプロジェクトにありました。そこで、以下のように受信機を実装して解決しました。 <receiver Android:name="receiver name" 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="your package"/> </intent-filter> </receiver>それがあなたの助けになることを願っています:-)。

0
Hay Thi

データがあるときにプッシュを受信できないOnePlus2がありました。 logcatと接続したときに、このエラーの多くを見ましたが、関連しているかどうかはわかりません。

私はそれに対応する設定を見つけることをあきらめ、デバイスを工場出荷時の状態にリセットしました。 OxygenOSを実行しているOnePlusデバイスは、ソフトウェアの更新をインストールするときに奇妙な構成エラーを受け取り、工場出荷時の状態にリセットしてからGoogleバックアップから復元すると、根本的な問題を理解するのにかかるよりも速く動作します(そして、ユーザーが根本的な問題を修正するための適切なアクセス権)。

0
binki

Googleサービスの「バックグラウンドデータアクセス」を有効にしていました。 [データ使用オプション]の[バックグラウンドデータを制限する]のチェックを外すことで動作します。

0
Gowtham Venkat

私にとっては、goolgeは私のIPをブロックしました!プールから新しいIPを取得するためにDSL接続をリセットする必要がありましたが、すべてが再び機能しました。とにかく今は働いています、私はこれが誰か他の人を助けることを願っています:)

0
D.Snap