web-dev-qa-db-fra.com

GCM Android et plusieurs jetons

Je m'inscris dans GCM avec GoogleCloudMessaging.getInstance (context); et enregistrez le jeton reçu sur le périphérique. Ensuite, envoyez-le au serveur et il est associé au compte utilisateur. Si je désinstalle mon application sans me déconnecter, que je l'installe à nouveau et que je me connecte avec un autre utilisateur, je reçois un nouveau jeton et l'envoie au serveur. Et quand les envois sont envoyés au premier utilisateur, je les vois lorsque je me suis connecté avec le deuxième utilisateur.

Pourquoi GCM m'envoie-t-il différents jetons et comment puis-je gérer cela?

15
earsonheart

Bienvenue dans le monde merveilleux des messages en double de Google Cloud Messaging. Lorsque cela se produit, le moteur GCM permet au Canonical IDs de le résoudre. Cela peut arriver parce que vous vous êtes inscrit avec plusieurs identifiants pour le même périphérique ou parce que le serveur GCM n'a pas reçu l'appel unregister() lors de la désinstallation de l'application. L'utilisation d'identifiants canoniques définira votre identifiant comme étant le dernier enregistrement que vous avez effectué.

Selon le GCM reference à ce sujet:

ID canoniques

Du côté du serveur, tant que l'application se comporte bien, tout devrait fonctionner normalement. Toutefois, si un bogue dans l'application déclenche plusieurs inscriptions pour le même périphérique, il peut être difficile de réconcilier un état et vous risquez de vous retrouver avec des messages en double.

GCM fournit une installation appelée "ID d'enregistrement canonique" pour récupérer facilement de ces situations. Un identifiant d'enregistrement canonique est défini comme l'identifiant du dernier enregistrement demandé par votre application. C'est l'ID que le serveur doit utiliser lors de l'envoi de messages au périphérique.

Si plus tard, vous essayez d'envoyer un message en utilisant un autre ID d'enregistrement, GCM traitera la demande comme d'habitude, mais inclura l'ID d'enregistrement canonique dans le champ registration_id de la réponse. Assurez-vous de remplacer l'ID d'enregistrement stocké sur votre serveur par cet ID canonique, car à terme, l'ID que vous utilisez cessera de fonctionner.

Plus d'infos ici .

De plus, il existe un cas pratique sur la façon de procéder, cela pourrait être utile:

11
nKn

J'ai rencontré des modifications de l'ID d'enregistrement lors de la désinstallation de l'application, en essayant d'envoyer des messages à l'application alors qu'elle était désinstallée (jusqu'à ce que je reçoive une erreur NotRegistered), puis en l'installant à nouveau.

Costin Manolache de Google suggère de gérer les modifications d’identification d’enregistrement de cette façon:

La solution proposée consiste à générer votre propre identifiant aléatoire, enregistré sous forme de préférence partagée, par exemple. Lors de chaque mise à niveau de l'application, vous pouvez télécharger l'identifiant et le nouvel identifiant d'enregistrement potentiellement nouveau. Cela peut également aider à suivre et à déboguer les modifications de mise à niveau et d’enregistrement côté serveur.

Bien sûr, cela ne fonctionne que lorsque l'application reste installée (car les préférences partagées sont supprimées avec l'application). Toutefois, si l'appareil dispose d'un stockage externe, vous pouvez y stocker votre identifiant et, lorsque l'application est réinstallée, chargez l'identifiant stocké à partir du stockage externe. De cette façon, vous saurez que le nouvel ID d'enregistrement et l'ancien ID d'enregistrement appartiennent au même appareil.

En outre, vous devez gérer les réponses canoniques d’ID d’enregistrement de Google sur votre serveur, comme indiqué dans l’autre réponse.

5
Eran

Vous pouvez envoyer un identifiant d'appareil Android avec un identifiant d'enregistrement. L'identifiant de l'appareil Android est unique et reste le même lors de la réinstallation de l'application. Il ne change que si l'appareil est réinitialisé.

Exemple: Comment obtenir un identifiant matériel unique dans Android?

1
Said Ali Samed

L'envoi d'une notification push à plusieurs appareils est identique à celui que nous envoyons à un appareil individuel. Enregistrez simplement le jeton d'enregistrement de tous les périphériques enregistrés sur votre serveur. Et lorsque vous appelez la notification Push avec curl (je suppose que vous utilisez php en tant que serveur), placez tous les identifiants d'enregistrement dans un tableau. Ceci est un exemple de code

<?php
//Define your GCM server key here 
define('API_ACCESS_KEY', 'your server api key');

//Function to send Push notification to all 
function sendToAll($message)
{
    $db = new DbOperation();
    $tokens = $db->getAllToken();
    $regTokens = array();
    while($row = $tokens->fetch_assoc()){
        array_Push($regTokens,$row['token']);
    }
    sendNotification($regTokens,$message);
}


//function to send Push notification to an individual 
function sendToOne($email,$message){
    $db = new DbOperation();
    $token = $db->getIndividualToken($email);
    sendNotification(array($token),$message);
}


//This function will actually send the notification
function sendNotification($registrationIds, $message)
{
    $msg = array
    (
        'message' => $message,
        'title' => 'Android Push Notification using Google Cloud Messaging',
        'subtitle' => 'www.simplifiedcoding.net',
        'tickerText' => 'Ticker text here...Ticker text here...Ticker text here',
        'vibrate' => 1,
        'sound' => 1,
        'largeIcon' => 'large_icon',
        'smallIcon' => 'small_icon'
    );

    $fields = array
    (
        'registration_ids' => $registrationIds,
        'data' => $msg
    );

    $headers = array
    (
        'Authorization: key=' . API_ACCESS_KEY,
        'Content-Type: application/json'
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://Android.googleapis.com/gcm/send');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    $result = curl_exec($ch);
    curl_close($ch);

    $res = json_decode($result);

    $flag = $res->success;
    if($flag >= 1){
        header('Location: index.php?success');
    }else{
        header('Location: index.php?failure');
    }
}

Dans le code ci-dessus, nous récupérons le jeton d'enregistrement de la table mysql. Pour envoyer à tous les appareils, nous avons besoin de tous les jetons. Et pour envoyer un appareil individuel, nous avons besoin d'un jeton pour cet appareil uniquement.

Source:Exemple de messagerie Google Cloud

0
Reyaan Roy

d’abord lorsque vous envoyez une notification, envoyez l’identifiant d’utilisateur avec lui et demandez si l’identifiant est en sharedpreference == comming ou non

si vous envoyez des notifications à tous les utilisateurs et que l'un d'entre eux en ait 2, alors qu'il ne devrait en recevoir qu'un seul

Créez un fichier sur votre serveur et avec un nombre quelconque, dites 0, puis, lorsque vous souhaitez envoyer une notification, envoyez ce numéro avec ce numéro, puis ajoutez-en un à ce numéro.

Dans une application Android, ajoutez une variable et laissez cette variable = la variable venant du serveur après avoir ajouté la notification, mais vous devez demander à if(number_in_your_service!=server_number) // ajouter une notification.

n'importe quel nombre de notifications que vous n'en envoyez qu'une apparaîtra

public class GcmIntentService extends IntentService {
  public static int openintent;
  public static final int NOTIFICATION_ID = 1;
  private static final String TAG = "GcmIntentService";

  private static String number_in_your_service="somethingneversend";
  NotificationCompat.Builder builder;

  public GcmIntentService() {
    super("GcmIntentService");
  }

  @Override
  protected void onHandleIntent(Intent intent) {
    Bundle extras = intent.getExtras();
    GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
    String messageType = gcm.getMessageType(intent);

    if (!extras.isEmpty()) { // has effect of unparcelling Bundle
      if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
      } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
        // If it's a regular GCM message, do some work.
      } else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
        // This loop represents the service doing some work.
        for (int i = 0; i < 5; i++) {
          Log.i(TAG, "Working... " + (i + 1) + "/5 @ " + SystemClock.elapsedRealtime());
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
          }
        }
        Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
        // Post notification of received message.
        sendNotification(extras);
        Log.i(TAG, "Received: " + extras.toString());
      }
    }
    // Release the wake lock provided by the WakefulBroadcastReceiver.
    GcmBroadcastReceiver.completeWakefulIntent(intent);
  }

  private void sendNotification(Bundle extras) {

    if((extras.getString("server_number")).equals(number_in_your_service)) {

      Intent intent = new Intent(this, Main_Page_G.class);
      intent.putExtra("frame",100);
      intent.putExtra("bundle",extras);
      final PendingIntent contentIntent = PendingIntent.getActivity(this,
            120, intent, PendingIntent.FLAG_UPDATE_CURRENT);
      NotificationManager mNotificationManager;
      NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
            GcmIntentService.this).setContentTitle("name")
            .setContentText("content")
            .setDefaults(Notification.DEFAULT_SOUND)
            .setContentInfo("Test")
            .setSmallIcon(R.drawable.rehablogo2)
            .setAutoCancel(true);
      mBuilder.setContentIntent(contentIntent);
      mNotificationManager = (NotificationManager) GcmIntentService.this
            .getSystemService(Context.NOTIFICATION_SERVICE);
      mNotificationManager.notify(id, mBuilder.build());
      id=Integer.parseInt(extras.getString("id"));
    }
  }
}
0
Mohamed Atef