Firebase Cloud Messaging-gestion de la déconnexion

comment gérer la situation, lorsque l'utilisateur se déconnecte de mon application et que je ne veux plus qu'il reçoive des notifications à l'appareil.

j'ai essayé

FirebaseInstanceId.getInstance().deleteToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)

Mais je continue à recevoir les notifications de mon appareil registration_id.

j'ai aussi fait en sorte que ce soit le token que je devrais supprimer:

FirebaseInstanceId.getInstance().getToken(FirebaseInstanceId.getInstance().getId(), FirebaseMessaging.INSTANCE_ID_SCOPE)

ou tout simplement FirebaseInstanceId.getInstance().getToken()).

j'ai aussi essayé FirebaseInstanceId.getInstance().deleteInstanceId(), mais alors la prochaine fois que j'appelle FirebaseInstanceId.getInstance.getToken Je ne reçois rien (cela fonctionne sur le second essayer.)

je suppose que, après deleteInstanceId j'ai tout de suite appeler getToken() encore une fois, mais ça ressemble à un piratage. Et il y a également cette réponse qui dit que cela ne devrait pas être fait, mais il propose de supprimer le token qui apparemment ne fonctionne pas.

Alors, quelle est la bonne méthode pour gérer cela?

28
demandé sur Community 2017-04-03 22:56:58

4 réponses

Ok. J'ai donc réussi à faire quelques tests et j'ai conclu ce qui suit:

  1. deleteToken() est la contrepartie de getToken(String, String), mais pas pour getToken().

il ne fonctionne que si L'ID de L'expéditeur que vous passez est un ID de L'expéditeur différent (pas le même ID qui peut être vu dans vos services google).json). Par exemple, vous voulez permettre à un autre Serveur pour envoyer à votre application, vous appeler getToken("THEIR_SENDER_ID", "FCM") donner l'autorisation pour envoyer à votre application. Ce renvoie un jeton d'enregistrement différent qui ne correspond qu'à l'expéditeur spécifique.

dans le futur, si vous choisissez de supprimer leur l'autorisation pour envoyer à votre application, vous devrez alors vous rendre l'utilisation de deleteToken("THEIR_SENDER_ID", "FCM"). Cela annulerait le jeton correspondant, et lorsque l'Expéditeur tente d'envoyer un message, comme le comportement voulu, ils recevront un NotRegistered erreur.

  1. pour supprimer le jeton pour votre propre Expéditeur, le corriger la manipulation est d'utiliser deleteInstanceId().

mention Spéciale cette réponse par @Prince, spécifiquement l'échantillon de code pour m'aider avec ça.

comme @MichałK le fait déjà dans son post, Après avoir appelé le deleteInstanceId(),getToken() devrait être appelé pour envoyer une demande pour un nouveau jeton. Cependant, vous n'avez pas à appeler une seconde fois. Tant que onTokenRefresh() est implémenté, il devrait se déclencher automatiquement en vous fournissant le nouveau jeton.

Pour faire court, deleteInstanceId()>getToken() > case onTokenRefresh().

Remarque:: Appel de deleteInstanceId() ne supprimera pas seulement le token pour votre propre application. Il supprimera tous les abonnements à des sujets et tous les autres Jetons associés à l'instance app.


Êtes-vous positif que vous appelez deleteToken() correctement? La valeur pour audience devrait être (aussi vu de ma réponse que vous avez lié) est "défini à l'ID de l'expéditeur du serveur d'application". Vous êtes de passage getId() valeur qui n'est pas le même que l'ID de l'Expéditeur (il contient l'instance de l'application valeur de l'id). De plus, comment envoyez-vous le message (serveur App ou Console de Notifications)?

getToken() et getToken(String, String) renvoie des jetons différents. Voir ma réponse ici.

j'ai aussi essayé FirebaseInstanceId.getInstance().deleteInstanceId(), mais alors la prochaine fois que j'appelle FirebaseInstanceId.getInstance.getToken Je ne reçois rien (cela fonctionne à la seconde tentative).

C'est probablement parce que l' la première fois que vous appelez l' getToken(), c'est encore en cours de génération. C'est juste le comportement voulu.

je suppose que, après deleteInstanceId j'ai tout de suite appeler

Pas vraiment. C'est comment vous obtiendrez le nouveau jeton généré (à condition qu'il soit déjà généré). Donc, je pense que c'est bien.

24
répondu AL. 2017-05-23 12:02:34

Essayez ceci

je travaillais sur la même condition ,quand j'avais fait ma déconnexion de mon application mais le problème était qu'après m'être déconnecté je recevais toujours la notification de poussée de la base de tir.so tried to supprimer le jeton firebase mais après avoir effacé le token dans la méthode logout quand l'application arrive dans la méthode login ses shows NULL quand j'ai essayé d'obtenir le token friebase ,donc mon application s'est écrasée après avoir supprimé le token firebase.Après 2 jours de travail j'ai enfin obtenu mes solutions..espérons que cela fonctionnera pour vous aussi.

  1. dans votre méthode de déconnexion, supprimez le jeton firebase en arrière-plan parce que vous ne pouvez pas supprimer le jeton firebase dans la méthode principale

    new AsyncTask<Void,Void,Void>()
    {
        @Override
        protected Void doInBackground(Void... params)
        {
            {
                try
                {
                    FirebaseInstanceId.getInstance().deleteInstanceId();
                } catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void result)
        {
            //call your activity where you want to land after log out
        }
    }.execute();
    
  2. dans votre méthode de connexion de l'activité de générer de nouveau firebase jeton(préférez la méthode onresume)

    new AsyncTask<Void,Void,Void>()
    {
        @Override
        protected Void doInBackground(Void... params)
        {
    
            String token = FirebaseInstanceId.getInstance().getToken();
            while(token == null)//this is used to get firebase token until its null so it will save you from null pointer exeption
            {
                token = FirebaseInstanceId.getInstance().getToken();
            }
            return null;
        }
        @Override
        protected void onPostExecute(Void result)
        {
    
        }
    }.execute();
    

Dans mon cas sa fonctionne pour moi si pas de commentaires moi quel est le problème

11
répondu Sunil 2017-08-12 06:43:05

je sais je suis en retard pour la fête. deleteInstanceId() devrait être appelé à partir du fil d'arrière-plan puisque c'est un appel de blocage. Il suffit de cocher la méthode deleteInstanceId()FirebaseInstanceId () classe.

@WorkerThread
public void deleteInstanceId() throws IOException {
    if (Looper.getMainLooper() == Looper.myLooper()) {
        throw new IOException("MAIN_THREAD");
    } else {
        String var1 = zzh();
        this.zza(this.zzal.deleteInstanceId(var1));
        this.zzl();
    }
}  

vous pouvez lancer un IntentService pour supprimer l'ID d'instance et les données qui y sont associées.

1
répondu Sarweshkumar C R 2018-07-26 06:18:05

j'ai fait une brève recherche sur ce qui serait la solution la plus élégante pour récupérer le contrôle complet (abonnez-vous et désabonnez-vous à la FCM) comme avant. Activez et désactivez le FCM après que l'utilisateur s'est connecté.

Étape 1. - Empecher l'initialisation automatique

Firebase maintenant gérer l' InstanceID et tout ce qui doit générer un token d'enregistrement. Tout d'abord, vous devez prévenir auto initialisation. Basé sur le fonctionnaire mis en place la documentation vous devez ajouter ces méta-données valeurs AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<application>

  <!-- FCM: Disable auto-init -->
  <meta-data android:name="firebase_messaging_auto_init_enabled"
             android:value="false" />
  <meta-data android:name="firebase_analytics_collection_enabled"
             android:value="false" />

  <!-- FCM: Receive token and messages -->
  <service android:name=".FCMService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
  </service>

</application>

Maintenant vous avez désactivé le processus de demande automatique de token. En même temps vous avez une option pour l'activer à nouveau à l'exécution par code.

Étape 2. - Mettre en œuvre enableFCM() et disableFCM() fonctions

si vous activez à nouveau l'initialisation automatique, alors vous avez reçu un nouveau token immédiatement, donc c'est un parfait façon de mettre en œuvre l' enableFCM() méthode. Toutes les informations d'abonnement attribuées à InstanceID, donc lorsque vous les supprimez, initialisez pour désabonner tous les sujets. De cette façon, vous pouvez mettre en œuvre disableFCM() méthode, il suffit de désactiver auto-init avant de l'effacer.

public class FCMHandler {

    public void enableFCM(){
        // Enable FCM via enable Auto-init service which generate new token and receive in FCMService
        FirebaseMessaging.getInstance().setAutoInitEnabled(true);
    }

    public void disableFCM(){
        // Disable auto init
        FirebaseMessaging.getInstance().setAutoInitEnabled(false);
        new Thread(() -> {
            try {
                // Remove InstanceID initiate to unsubscribe all topic
                // TODO: May be a better way to use FirebaseMessaging.getInstance().unsubscribeFromTopic()
                FirebaseInstanceId.getInstance().deleteInstanceId();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();
    }

}

Étape 3. - FCMService mise en place du jeton et le message de réception

dans la dernière étape, vous devez recevoir le nouveau token et l'envoyer directement à votre serveur. D'autres part, vous recevrez votre message de données et juste faire ce que vous voulez.

public class FCMService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String token) {
        super.onNewToken(token);
        // TODO: send your new token to the server
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
        String from = remoteMessage.getFrom();
        Map data = remoteMessage.getData();
        if (data != null) {
            // TODO: handle your message and data
            sendMessageNotification(message, messageId);
        }
    }

    private void sendMessageNotification(String msg, long messageId) {
        // TODO: show notification using NotificationCompat
    }
}

je pense que cette solution est claire, simple et transparente. J'ai testé dans un environnement de production et ça marche. J'espère que ça a été utile.

1
répondu János Sicz-Mesziár 2018-08-09 22:02:00