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:
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?
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);
}
}
Le problème est résolu, dans mon cas c'était un peu plus compliqué.
La mauvaise horloge a posé problème pour moi. :)
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.
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.
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)
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é
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
}
}
Pour moi, il y avait un problème de connexion. Changer de connexion Internet a résolu mon problème
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
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).
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.
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 :-)
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 :-).
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).
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!
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 :)