web-dev-qa-db-fra.com

Android: le jeton Firebase est nul à la première exécution

J'utilise FCM pour fournir des notifications dans mon application. Tout a bien fonctionné, mais je me suis rendu compte maintenant que, lorsque j'installe mon application à l'aide de Android Studio (pas à partir de GooglePlay), le jeton est nul au premier lancement. Lorsque je ferme et relance mon application, le Le jeton n’est plus nul. Quelle est la cause de ce problème et comment puis-je l’éviter?

InstanceIDService:

public class InstanceIDService extends FirebaseInstanceIdService {

    @Override
    public void onTokenRefresh() {

        String token = FirebaseInstanceId.getInstance().getToken();
        registerToken(token);
    }

    private void registerToken(String token) {

        OkHttpClient client = new OkHttpClient();
        RequestBody body = new FormBody.Builder()
                .add("Token",token)
                .build();

        Request request = new Request.Builder()
                .url("url_to_registration_script")
                .post(body)
                .build();

        try {
            client.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Dans MainActivity:

FirebaseMessaging.getInstance().subscribeToTopic("topic");
String token = FirebaseInstanceId.getInstance().getToken();
Log.d("TOKEN", token);

Le dernier journal renvoie la valeur null lorsque l'application est installée et démarrée pour la première fois

Script d'inscription:

 <?php 
 if (isset($_POST["Token"])) {

       $_uv_Token=$_POST["Token"];
       $conn = mysqli_connect("localhost","user","pass","db") or die("Error connecting");
       $q="INSERT INTO users (Token) VALUES ( '$_uv_Token') "
          ." ON DUPLICATE KEY UPDATE Token = '$_uv_Token';";

  mysqli_query($conn,$q) or die(mysqli_error($conn));
  mysqli_close($conn);
}
?>
28
Matej Košút

Le jeton est récupéré de manière asynchrone au premier démarrage de l'application. Vous devez attendre que onTokenRefresh() soit appelé dans votre FirebaseInstanceIdService avant que le jeton ne soit accessible.

30
patloew

désinstaller l'application de l'émulateur et l'exécuter à nouveau, de sorte que la méthode onTokenRefreshed sera appelée à nouveau.

Pour vérifier si vous êtes déjà inscrit et que vous voulez juste connaître le nom de la FCM

String refreshedToken = FirebaseInstanceId.getInstance().getToken();

ajoutez la ligne ci-dessus dans la classe MyFirebaseMessagingService n'importe où (dans la méthode oncreate) et effectuez simplement un Toast ou enregistrez le refreshedToken.

8
kashyap k bandi

Il suffit de remplacer:

String token = instanceID.getToken();

avec:

String token = instanceID.getToken($SENDER_ID, "FCM");

et ça va marcher.

5
Alaa AlDarf

Je faisais face au même problème. J'ai parcouru beaucoup de SO billets et autres forums et j'ai trouvé une solution qui fonctionnait pour moi. La documentation de FCM recommande d'utiliser cette méthode pour obtenir un jeton.

String refreshedToken = FirebaseInstanceId.getInstance().getToken();

J'ai trouvé un message en ligne (je m'excuse, je ne me souviens plus lequel. Je l'ai trouvé il y a longtemps) qui utilisait cette méthode à la place:

String refreshedToken = FirebaseInstanceId.getInstance().getToken() (String authorizedEntity, String scope);

La documentation FCM décrit la première méthode comme suit:

Renvoie le jeton principal du projet Firebase par défaut.

Alors que le second est décrit comme:

Renvoie un jeton qui autorise une entité à exécuter une action pour le compte de l'application identifiée par l'ID d'instance. Ceci est similaire à un jeton OAuth2 sauf que cela s'applique à l'instance d'application plutôt qu'à un utilisateur. Par exemple, pour obtenir un jeton pouvant être utilisé pour envoyer des messages à une application via FirebaseMessaging, définissez l'ID de l'expéditeur et définissez-le sur "FCM".

J'ai cherché à savoir pourquoi le premier appel de méthode prenait plus de temps pour renvoyer un jeton, mais je n'ai pas encore trouvé de réponse. J'espère que cela t'aides.

3
Marline

Parfois, des problèmes de réseau peuvent survenir, même Internet fonctionne correctement .... vérifiez votre classe FirebaseInstancId définie dans le fichier manifeste dans votre projet Android.

2
suresh gupta

Même j'ai eu le même problème. J'avais donné l'instruction de journal pour imprimer le jeton dans l'activité de lancement de mon créateur. Il faut du temps pour actualiser le jeton une fois que vous désinstallez l'application. C'est pourquoi vous obtenez nul. Vous devez attendre un peu pour que le jeton soit actualisé.

2
Rakesh

J'avais le même problème dans un appareil Android 4.2. Donc, pour résoudre le problème, vérifiez d'abord si votre service, dans le manifeste, a la priorité suivante:

    <service
        Android:name=".other.MyFirebaseInstanceIDService"
        Android:exported="false">
        <intent-filter Android:priority="1000">
            <action Android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
        </intent-filter>
    </service>

Deuxièmement, utilisez une intention de diffusion pour notifier votre MainActivity qui a modifié le jeton:

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

@Override
public void onTokenRefresh() {
    // Get updated InstanceID token.
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();

    final Intent intent = new Intent("tokenReceiver");
    final LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
    intent.putExtra("token",refreshedToken);
    broadcastManager.sendBroadcast(intent);
}

Ensuite, dans MainActivity, dans onCreate, ajoutez ceci:

     @Override
protected void onCreate(Bundle savedInstanceState) {
...
LocalBroadcastManager.getInstance(this).registerReceiver(tokenReceiver,
            new IntentFilter("tokenReceiver"));
}

et, dans MainActivity, ajoutez un nouveau BroadcastReceiver:

BroadcastReceiver tokenReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String token = intent.getStringExtra("token");

        if(token != null)
        {
            Log.e("firebase", String.valueOf(token));

            // send token to your server 
        }

    }
};
1

Le problème le plus important auquel j'ai été confronté après avoir écrit le code correct est le suivant:

1
Chirag Joshi

Puisque la méthode getToken() est obsolète , vous devez remplacer le avec un auditeur.

Il suffit de remplacer String token = FirebaseInstanceId.getInstance().getToken(); par l'extrait de code suivant:

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();

                                // Log and toast
                                String msg = getString(R.string.msg_token_fmt, token);
                                Log.d(TAG, msg);
                                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
                            }
});

Vous pouvez trouver la documentation officielle de Google ici: https://firebase.google.com/docs/cloud-messaging/Android/client

Et un post de Nice medium vous aidera également: https://medium.com/@cdmunoz/fcm-getinstance-gettoken-in-Android-is-now-deprecated-how-to-fix-it -3922a94f4fa4

1
user2912903

Je suis juste tombé dans le même problème et c'est la façon dont je l'ai corrigé. Appelez le bloc quelque part dans la méthode onCreate() de votre activité. Je souhaite envoyer le jeton sur mon serveur Parse. Vous devez donc le modifier en fonction de vos besoins.

Ceci est l'échantillon que j'ai suivi.

private void subscribeUserToParse() {
        String deviceToken = FirebaseInstanceId.getInstance().getToken();
        if (TextUtils.isEmpty(deviceToken)) {
            Intent intent = new Intent(this, MyFirebaseInstanceIDService.class);
            startService(intent);
            return;
        }

        User user = UserUtil.retrieveUserFromDB(mRealm);
        String objectId = user.getParseObjectId();
        if (!TextUtils.isEmpty(objectId)) {
            ParseUtils.subscribeWithUsersObjectId(objectId, deviceToken);
        }
    }
1
Hesam