Firebase (FCM) comment obtenir un jeton

92

C'est la première fois que j'utilise FCM.

Je télécharge un échantillon de firebase / quickstart-android et j'installe le FCM Quickstart. Mais je ne peux pas obtenir de jeton du journal, même appuyez sur le bouton LOG TOKEN dans l'application.

Ensuite, j'essaie d'envoyer un message avec la console Firebase et de définir le ciblage du nom de mon package d'application. J'ai reçu des messages entrants.

Je veux savoir si FCM peut être utilisé? GCM tout est ok.

Solution:

Parce que je ne suis pas un développeur Android, juste un développeur backend. Il me faut donc un certain temps pour le résoudre. À mon avis, il y a quelques bugs dans l'exemple d'application.

entrez la description de l'image ici

Code:

RegistrationIntentService.java

public class RegistrationIntentService extends IntentService {

    private static final String TAG = "RegIntentService";


    public RegistrationIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String token = FirebaseInstanceId.getInstance().getToken();
        Log.i(TAG, "FCM Registration Token: " + token);
    }
}

MyFirebaseInstanceIDService.java

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    /**
     * Called if InstanceID token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the InstanceID token
     * is initially generated so this is where you would retrieve the token.
     */
    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        // TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

    /**
     * Persist token to third-party servers.
     * <p>
     * Modify this method to associate the user's FCM InstanceID token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private void sendRegistrationToServer(String token) {
        // Add custom implementation, as needed.
    }
}

Ajoutez ceci dans le fichier MainActivity.java.

 Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);

Après avoir fait ci-dessus, vous obtenez le jeton dans Logcat. Mais finalement, je trouve un moyen pratique de l'obtenir. Utilisez simplement le mode débogage pour installer l'exemple d'application et vous pourrez obtenir le jeton lors de la première installation.

Mais je ne sais pas pourquoi il ne peut pas imprimer le journal lorsque je l'installe. Peut-être être lié au système mobile.

Et puis pourquoi je ne peux pas obtenir la notification. FirebaseMessagingService.onMessageReceived n'a pas appelé sendNotification

wyx
la source
si le journal est atteint, il affichera le jeton avec lui dans l'exemple d'application
Shubhank
Non, a dit l'exemple d'application. Il n'affichera le jeton dans logcat que si j'appuie sur le bouton. Mais je ne trouve rien dans logcat. @ Shubhank
wyx
décommenter ces lignes String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav

Réponses:

120

PLUS RAPIDE ET BON POUR LE PROTOTYPE

La solution rapide consiste à le stocker dans sharedPrefs et à ajouter cette logique à la onCreateméthode de votre MainActivity ou de la classe qui étend Application.

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(this, instanceIdResult -> {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken", newToken);
    getActivity().getPreferences(Context.MODE_PRIVATE).edit().putString("fb", newToken).apply();
});

Log.d("newToken", getActivity().getPreferences(Context.MODE_PRIVATE).getString("fb", "empty :("));

UNE MANIÈRE PLUS PROPRE

Une meilleure option consiste à créer un service et à conserver une logique similaire. Commencez par créer un nouveau service

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    @Override
    public void onNewToken(String s) {
        super.onNewToken(s);
        Log.e("newToken", s);
        getSharedPreferences("_", MODE_PRIVATE).edit().putString("fb", s).apply();
    }

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
    }

    public static String getToken(Context context) {
        return context.getSharedPreferences("_", MODE_PRIVATE).getString("fb", "empty");
    }
}

Et puis ajoutez-le au fichier AndroidManifest

<service
        android:name=".MyFirebaseMessagingService"
        android:stopWithTask="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
</service>

Enfin, vous pouvez utiliser une méthode statique de votre service MyFirebaseMessagingService.getToken(Context);

LE PLUS RAPIDE MAIS DÉPRECÉ

Log.d("Firebase", "token "+ FirebaseInstanceId.getInstance().getToken());

Cela fonctionne toujours lorsque vous utilisez une bibliothèque Firebase plus ancienne que la version 17.xx

Eliasz Kubala
la source
6
Mais la deuxième approche ne fonctionne que jusqu'à ce que les préférences partagées soient effacées. Que faire si les données de l'application sont effacées et que la valeur de la chaîne est perdue? Android n'appelle pas "onNewtoken ()" car il n'y a pas de nouveau jeton. Mais alors comment demander le jeton? Partout, il est dit "utilisez simplement onNewToken ()" mais cette méthode ne s'exécute que lorsqu'il y a un nouveau jeton. Disons que cette méthode a déjà été exécutée, mais nous n'avons pas pris la peine de stocker le jeton. Plus tard, nous effectuons une vérification et voyons que le jeton n'est pas défini, que faire alors? Comment faire pour que FCM me répète le jeton?
JeneralJames
1
Vous pouvez utiliser à la FirebaseInstanceId.getInstance().getInstanceId()place de FirebaseInstanceId.getInstance().getToken(), voir cette réponse
Vadim Kotov
24

Une information important.

si le service google play est suspendu ou ne fonctionne pas, alors le jeton de retour fcm = null

Si le service de lecture fonctionne correctement, la FirebaseInstanceId.getInstance().getToken()méthode retournetoken

Log.d("FCMToken", "token "+ FirebaseInstanceId.getInstance().getToken());
Yogesh Rathi
la source
Oui, mais cela arrive très souvent
Hoang Duc Tuan
Le jeton est mis en cache (in-mem très probablement) après avoir été récupéré une fois. Cela signifie donc que vous devez le récupérer une fois ou demander à Firebase de réémettre un autre jeton pour vous d'une manière ou d'une autre. Voir ici pour savoir comment récupérer manuellement stackoverflow.com/a/51630819/2102748
milosmns
20

L'équipe derrière Firebase Android SDK change un peu l'API. J'ai implémenté la logique «Token to Server» comme ceci:

Dans mon instance de FirebaseMessagingService:

public class FirebaseCloudMessagingService extends FirebaseMessagingService {

    ...

    @Override
    public void onNewToken(String token) {
        // sending token to server here
    }

    ...

}

Gardez à l'esprit que le jeton est par appareil et qu'il peut être mis à jour par Firebase quelle que soit votre logique de connexion. Donc, si vous avez la fonctionnalité de connexion et de déconnexion, vous devez prendre en compte des cas supplémentaires:

  1. Lorsqu'un nouvel utilisateur se connecte, vous devez lier le jeton au nouvel utilisateur (l'envoyer au serveur). Parce que le jeton peut être mis à jour pendant la session de l'ancien utilisateur et que le serveur ne connaît pas le jeton du nouvel utilisateur.
  2. Lorsque l'utilisateur se déconnecte, vous devez dissocier le jeton. Parce que l'utilisateur ne devrait plus recevoir de notifications / messages.

En utilisant la nouvelle API, vous pouvez obtenir un jeton comme celui-ci:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
        @Override
        public void onSuccess(InstanceIdResult instanceIdResult) {
            String token = instanceIdResult.getToken();
            // send it to server
        }
    });

Bonne chance!

rzaaeeff
la source
Essayer d'obtenir la valeur en dehors d'OnSuccess donne null.
DragonFire
La fonctionnalité de connexion / déconnexion n'a rien à voir avec les messages Push, il s'agit d'un cas d'utilisation métier spécifique. Par exemple, vous pouvez cibler les utilisateurs déconnectés avec des notifications marketing / promotionnelles pour les inciter à se reconnecter à l'application, auquel cas vous aurez besoin du jeton FCM. Mais la réponse est correcte en termes d'obtention du jeton.
milosmns
@milosmns, vous avez raison en termes de notifications marketing / promo. Une indication de l'état du jeton est toujours nécessaire. La solution simple serait de stocker les jetons non liés dans une sorte de table d'historique, puis d'utiliser ces jetons passés pour encourager l'utilisation à se
reconnecter
Hm, je ne sais pas combien de temps vous pouvez réutiliser le même jeton et quand exactement il est invalidé. Cela vaut la peine d'être étudié, car je suppose que vous devrez effacer cette table d'historique / cache / persistance une fois que les jetons deviennent invalides.
milosmns le
@milosmns, dans Firebaseland, les jetons n'expirent pas mais sont plutôt renouvelés. Lorsque vous déclenchez une activité liée au jeton avec l'API FCM, le jeton fourni est validé. Si le jeton n'est pas valide, vous recevrez une erreur: MissingRegistration ou une erreur: InvalidRegistration. Vous pouvez trouver plus de codes d'erreur ici: firebase.google.com/docs/cloud-messaging/…
rzaaeeff
13

Selon doc

Migrer une application client GCM vers FCM

onTokenRefresh()

Appelé uniquement si le jeton InstanceID est mis à jour

Ainsi, il n'appellera que la première fois lorsque vous installez une application sur votre appareil.

Je suggère donc de désinstaller manuellement votre application et d'essayer de l'exécuter à nouveau

certainement vous obtiendrez TOKEN

Gaurav
la source
2
ne pas réinstaller, désinstaller manuellement puis exécuter le projet,
Gaurav
décommenter ces lignes String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);
Gaurav
1
@Gaurav, comment puis-je obtenir un jeton après la deuxième connexion? onTokenRefreshne pas appeler chaque connexion. comment puis-je obtenir un jeton dans mon écran de connexion?
delavega66
3
@ de_la_vega_66, Vous devez stocker votre token lors de la première connexion
Gaurav
Votre service qui étend FirebaseInstanceIdService et a la méthode de rappel onTokenRefresh () DOIT être enregistré dans le fichier manifeste: <service android: name = "com.mypackage.name.MyInstanceIdService" android: exporté = "true"> <intent-filter> <action android: name = "com.google.firebase.INSTANCE_ID_EVENT" /> </intent-filter> </service>
Kirill Karmazin
9

Essaye ça. Pourquoi utilisez-vous RegistrationIntentService?

public class FirebaseInstanceIDService extends FirebaseInstanceIdService {    
    @Override
    public void onTokenRefresh() {    
        String token = FirebaseInstanceId.getInstance().getToken();    
        registerToken(token);
    }

    private void registerToken(String token) {

    }
}
FireUser
la source
8

Cette ligne devrait vous procurer le jeton FCM Firebase.

String token = FirebaseInstanceId.getInstance().getToken();
Log.d("MYTAG", "This is your Firebase token" + token);

Faites Log.d pour l'imprimer sur le moniteur Android.

Alphonsus Chen
la source
Il retourne null
Kishan Solanki
7

Au lieu de cela:

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
//        Get updated InstanceID token.
//        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);
//
//        TODO: Implement this method to send any registration to your app's servers.
//        sendRegistrationToServer(refreshedToken);
//
        Intent intent = new Intent(this, RegistrationIntentService.class);
        startService(intent);
    }
    // [END refresh_token]

Faites ceci:

    // [START refresh_token]
    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
//        Log.d(TAG, "Refreshed token: " + refreshedToken);

        // Implement this method to send token to your app's server
       sendRegistrationToServer(refreshedToken);

    }
    // [END refresh_token]

Et encore une chose:

Vous devez appeler la sendRegistrationToServer()méthode qui mettra à jour le jeton sur le serveur, si vous envoyez des notifications push depuis le serveur.

METTRE À JOUR:

Un nouveau jeton Firebase est généré ( onTokenRefresh()est appelé) lorsque:

  • L'application supprime l'ID d'instance
  • L'application est restaurée sur un nouvel appareil
  • L'utilisateur désinstalle / réinstalle l'application
  • L'utilisateur efface les données de l'application.
actifs depuis93
la source
J'ai dû supprimer l'ID d'instance FirebaseInstanceId.getInstance (). DeleteInstanceId () mais j'ai eu une ERREUR DE SERVICE,
Hardik9850
2
Vous devez exécuter FirebaseInstanceId.getInstance().deleteInstanceId()dans un autre fil de discussion
rockar06
5

En même temps, n'oubliez pas de l'inclure dans votre fichier manifeste pour recevoir l'identifiant du jeton

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
Kharak
la source
4

Dans firebase-messaging:17.1.0et plus récent le FirebaseInstanceIdService est obsolète, vous pouvez obtenir le onNewTokensur la FirebaseMessagingServiceclasse comme expliqué sur https://stackoverflow.com/a/51475096/1351469

Mais si vous voulez simplement obtenir le jeton à tout moment, vous pouvez maintenant le faire comme ceci:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener( this.getActivity(),  new OnSuccessListener<InstanceIdResult>() {
  @Override
  public void onSuccess(InstanceIdResult instanceIdResult) {
    String newToken = instanceIdResult.getToken();
    Log.e("newToken",newToken);
  }
});
jcesarmobile
la source
Cela peut-il être retourné, afin que la même fonction puisse être utilisée à de nombreux endroits ou nous devons copier et coller en raison de la nature asynchrone de firebase
DragonFire
4

La méthode getToken()est obsolète. Vous pouvez utiliser à la getInstanceId()place.

Si vous souhaitez gérer les résultats lors de la demande instanceId(token), vérifiez ce code.

    FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
    if (instanceIdResult != null) {
        String token = instanceIdResult.getToken();
        if (!TextUtils.isEmpty(token)) {
            Log.d(TAG, "retrieve token successful : " + token);
        }
    } else{
        Log.w(TAG, "instanceIdResult should not be null..");
    }
}).addOnFailureListener(e -> {
    //do something with e
}).addOnCanceledListener(() -> {
    //request has canceled
}).addOnCompleteListener(task -> Log.v(TAG, "task result : " + task.getResult().getToken()));
sNash
la source
3

Si vous utilisez une fonction d'authentification de Firebase, vous pouvez prendre un jeton en utilisant ceci:

//------GET USER TOKEN-------
FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getToken(true)
        .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
            public void onComplete(@NonNull Task<GetTokenResult> task) {
                if (task.isSuccessful()) {
                    String idToken = task.getResult().getToken();
                      // ...
                }
            }
        });

Fonctionne bien si l'utilisateur est connecté. getCurrentUser ()

Diego Venâncio
la source
2

essaye ça

FirebaseInstanceId.getInstance().instanceId.addOnSuccessListener(OnSuccessListener<InstanceIdResult> { instanceIdResult ->
             fcm_token = instanceIdResult.token}
Mohammad Rbabah
la source
1

pour ceux qui atterrissent ici, jusqu'à présent FirebaseInstanceIdServiceest obsolète maintenant, utilisez à la place:

public class MyFirebaseMessagingService extends FirebaseMessagingService {
    @Override
    public void onNewToken(String token) {
        Log.d("MY_TOKEN", "Refreshed token: " + token);

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // Instance ID token to your app server.
        // sendRegistrationToServer(token);
    }
}

et déclarer dans AndroidManifest

<application... >

<service android:name=".fcm.MyFirebaseMessagingService">
    <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>
</application>
user1908375
la source
1
FirebaseInstanceId.getInstance().getInstanceId().addOnCompleteListener(new OnCompleteListener<InstanceIdResult>() {
            @Override
            public void onComplete(@NonNull Task<InstanceIdResult> task) {
                if (!task.isSuccessful()) {
                    Log.w(TAG, "getInstanceId failed", task.getException());
                    return;
                }

                // Get new Instance ID token
                String **token** = task.getResult().getToken();

            }
        });
pruthwiraj.kadam
la source
-1

Vous pouvez utiliser les éléments suivants dans Firebase (FCM) pour obtenir le jeton:

FirebaseInstanceId.getInstance().getToken();
Ahmed Sayed
la source
2
La méthode getToken () est obsolète! La meilleure réponse, maintenant, est de @rzaaeeff.
Damiii
-9
Settings.Secure.getString(getContentResolver(),
                     Settings.Secure.ANDROID_ID);
Saurabh G.
la source
Ce code sert à obtenir l'ID Android de l'appareil, pas le jeton Firebase.
Syed Afeef