web-dev-qa-db-fra.com

Comment corriger l'erreur d'enregistrement de Google Cloud Messaging: SERVICE_NOT_AVAILABLE?

J'ai rencontré un problème étrange: j'utilise GCM dans mon application depuis assez longtemps et tout fonctionne parfaitement. Cependant, avant une publication sur Google Play, j'ai changé le nom de mon package d'application de com.Android.testapp à com.Android.recognition et cette fois GCM a cessé de fonctionner. Au début, j'ai eu une erreur GCM sender id not set on constructor et je l'ai corrigé en remplaçant getSenderIds(Context context), mais je ne peux plus obtenir d'ID d'enregistrement. Voici les messages de logcat: enter image description here

Comment puis-je réparer cela? Quand je suis passé à un nouveau paquet, j'ai tout changé dans le fichier manifeste pour le nouveau paquet:

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

Alors, quel est le problème derrière cela? Le fait de renommer le package d'application peut-il en être la cause ou existe-t-il une autre raison?

24

Cette erreur SERVICE_NOT_AVAILABLE indique que GCM Service n'est pas disponible dans le courant. Attendez et essayez après un certain temps. 

Cela arrive souvent (comme mon expérience), alors ne vous inquiétez pas. 


Voir la classe GCMConstants de GCM Lib. 

/**
     * 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";

Pour plus d’investigation, voir handleRegistration() of GCMBaseIntentService 

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);
        }
    }
30
Pankaj Kumar

Le problème est résolu, dans mon cas c'était un peu plus compliqué.

  1. Vérifiez que vous avez une connexion Internet active
  2. Vérifiez que vous avez l'autorisation Internet dans votre manifeste
  3. Assurez-vous que le nom du paquet est correct comme indiqué par Eran
  4. L'heure de l'appareil est correctement configurée. Même si tout est parfait, il échouera si l’horloge de l’appareil n’est pas réglée correctement.

La mauvaise horloge a posé problème pour moi. :)

42
Aman Gautam

Assurez-vous que vous avez modifié le nom du package dans la partie autorisations de votre manifeste:

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

J'ai eu une erreur similaire en raison d'un nom de package incorrect dans cette partie.

18
Eran

SERVICE_NOT_AVAILABLE est l'un des problèmes les plus frustrants avec Google Cloud Messaging. Il s'agit d'une exception levée par GoogleCloudMessaging.register(SENDER_ID), l'appel de fonction qui enregistre le périphérique pour les notifications Push et renvoie un ID d'enregistrement.

  1. SERVICE_NOT_AVAILABLE peut signifier que le périphérique de l'utilisateur ne peut pas lire la réponse à la demande d'enregistrement ou qu'un code d'erreur 500/503 a été renvoyé par le serveur. Les développeurs n’ont aucun moyen de corriger cette erreur car celle-ci est destinée à Google. Nous pouvons donc suggérer à l’aveugle que l’utilisateur doit réessayer dans quelques heures.
  2. SERVICE_NOT_AVAILABLE peut se produire sur certains appareils même si l'enregistrement a réussi. Ce problème peut être résolu en mettant en œuvre un récepteur de contournement permettant de récupérer le jeton lorsque l'appel échoue. J'ai implémenté cette solution de contournement qui a peut-être résolu le problème pour certains utilisateurs, mais j'ai quand même reçu de nombreuses autres plaintes de SERVICE_NOT_AVAILABLE.
  3. SERVICE_NOT_AVAILABLE peut se produire en raison d'une bibliothèque de services Google Play obsolète ou manquante sur l'appareil. Dans ce cas, l'application pourrait théoriquement demander à l'utilisateur de mettre à jour les services Google Play en ouvrant la liste correspondante de l'application Google Play. Cependant, l'application n'a aucune idée de pourquoi c'est pour cela que SERVICE_NOT_AVAILABLE a été lancée. Elle ne peut donc pas rediriger aveuglément l'utilisateur vers la page de l'application Services Google Play sur Google Play.
  4. SERVICE_NOT_AVAILABLE peut se produire lorsque l’horloge de l’appareil n’est pas synchronisée avec le réseau. Encore une fois, les développeurs n’ont aucun moyen de savoir qu’il s’agit du problème exact. Nous pouvons donc suggérer aveuglément à l’utilisateur de vérifier la synchronisation de leur horloge système, en espérant qu’ils font partie des rares dont les horloges ne sont pas synchronisées.
  5. SERVICE_NOT_AVAILABLE peut survenir lorsqu'un utilisateur root a supprimé l'application Hangouts/GTalk de son appareil (car ils l'ont considérée comme un bloatware). GCM est mis en œuvre et géré par Hangouts/GTalk. Il est donc impossible d’utiliser GCM sans ce dernier.
  6. SERVICE_NOT_AVAILABLE peut se produire si l'utilisateur exécute un appareil sur lequel les API Google ne sont pas installées (tel que le Kindle d'Amazon). Rien à faire ici, ces utilisateurs ne recevront jamais de notifications Push de votre application.

En savoir plus: http://eladnava.com/google-cloud-messaging-extremely-unreliable/

Ces problèmes à eux seuls suffisaient pour que je commence à chercher des solutions de rechange au MCG. Je recevrais tous les jours ou tous les deux jours une évaluation d'une étoile sur mon application, avec un commentaire contenant le message d'erreur affiché lorsqu'un SERVICE_NOT_AVAILABLE était émis. Je ne pouvais rien faire pour aider ces utilisateurs, car la majorité d'entre eux le recevaient pour des raisons indépendantes de leur volonté.

Une alternative à Google Cloud Messaging

Pushy ( https://pushy.me/ ) est une passerelle de notification Push autonome, totalement indépendante de GCM. Il maintient sa propre connexion de socket en arrière-plan, tout comme GCM, pour recevoir les notifications Push. Le protocole sous-jacent est MQTT, un protocole de publication/sous-protocole extrêmement léger, utilisant très peu de bande passante réseau et de batterie.

Un énorme avantage de Pushy est que le code d'envoi d'une notification Push (à partir du serveur) et d'enregistrement du périphérique pour les notifications Push est en réalité interchangeable entre GCM et Pushy. Cela rend très facile le passage à Pushy après la mise en œuvre de GCM et son abandon pour des raisons d’instabilité.

(Divulgation complète: j'ai fondé Pushy pour mes propres projets et réalisé que de nombreuses applications tireraient parti d'un tel service)

17
Elad Nava

Pour moi, l'heure de l'appareil n'était pas correcte. J'ai changé les paramètres de l'appareil pour utiliser "Date et heure automatiques", essayé à nouveau et tout bon.

À votre santé

13
Mahendra Liya

J'ai eu le même problème, mais aucune des solutions ci-dessus n'a résolu le problème dans mon cas. Heureusement, je l'ai récemment résolu et je veux expliquer comment, espérant que cela aidera d'autres personnes:

Dans mon cas, j’enregistrais le service Push dans une classe d’application personnalisée (qui est exécutée avant toute activité, ce qui explique que certaines choses n’aient pas été initialisées correctement). Le changer en activité principale a résolu le problème.

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

Pour moi, il y avait un problème de connexion. Changer de connexion Internet a résolu mon problème

3
Muhammad Aamir Ali

J'avais un problème similaire. A bien fonctionné sur un lien Google (Android 4.4.2), mais pas sur un Samsung Galaxy S3 (Android 4.1.2) . Je recevais SERVICE_NOT_AVAILABLE lors de l’enregistrement sur Samsung. Il s'est avéré que le temps sur Samsung était éteint. Il n'a pas été configuré pour une mise à jour automatique avec l'heure du réseau. Une fois que j'ai corrigé, GCM fonctionnait à merveille. Merci - Umesh

3
user3541251

Dans mon cas, la solution consistait à ajouter une nouvelle action de filtrage de l'intention, REGISTRATION, au manifeste, par https://snowdog.co/blog/dealing-with-service_not_available-google-cloud-messaging/

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

Je dois admettre que je suis surpris que cela fonctionne, étant donné que cela manque dans le didacticiel, mais sa suppression transforme définitivement un identifiant d'enregistrement réussi en une exception.

Remarque: utilisation de l’émulateur Nexus 5 API 21 (Lollipop).

3
Brian Marick

Pour moi, je me suis tourné de "l'accès aux données en arrière-plan" pour les services de Google en cochant la case "Limiter les données en arrière-plan" dans l'option d'utilisation des données sur mon Galaxy S4. Dès que je l'ai allumé, le problème est résolu sur le réseau cellarer. Sur Wifi, ça fonctionnait bien.

3
ahmadalibaloch

Pour moi, le problème était que le téléphone n'était pas connecté à Internet. Je me déconnecte et me connecte au Wi-Fi, et teste la connectivité avec Browser, puis à nouveau. Travaillé comme un charme :-)

2
Roozbeh Zabihollahi

Pour moi, le problème SERVICE_NOT_AVAILABLE était dans mon projet d'application à cause de la classe de destinataire . J'ai donc résolu le problème après avoir implémenté le destinataire de la manière suivante: __________<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> J'espère que cela vous aidera :-).

0
Hay Thi

J'avais un OnePlus2 qui ne pouvait pas recevoir de push quand sur des données. Lorsque je me suis connecté avec logcat, j’ai vu beaucoup de cette erreur, mais je ne sais pas si elle est liée.

J'ai arrêté d'essayer de trouver un réglage qui lui correspond et de réinitialiser l'appareil en usine. Les appareils OnePlus exécutant OxygenOS rencontrent parfois des erreurs de configuration étranges lors de l'installation de mises à jour logicielles. Une réinitialisation d'usine suivie d'une restauration à partir de Google Backup accélère le processus pour comprendre le problème sous-jacent (il se peut même que l'utilisateur ne le bon accès pour résoudre le problème sous-jacent).

0
binki

J'avais tourné de "l'accès aux données en arrière-plan" pour les services de Google. En décochant "Limiter les données d'arrière-plan" dans l'option Utilisation des données, cela fonctionne pour moi!

0
Gowtham Venkat

Pour moi, goolge a bloqué mon IP !! Je devais réinitialiser ma connexion DSL pour obtenir une nouvelle adresse IP de la piscine et tout fonctionnait à nouveau, idk pourquoi ils m'ont bloqué, peut-être pour avoir essayé plusieurs applications? Quoi qu'il en soit fonctionne maintenant, j'espère que cela aider quelqu'un d'autre :)

0
D.Snap