web-dev-qa-db-fra.com

Notification de Firebase Cloud Messaging de Java au lieu de Firebase Console

Firebase pour la première fois et rencontre des erreurs telles que l'ID de l'expéditeur et l'erreur d'authentification avec le statut HTTP 401 lorsque mon application Java) tente d'envoyer une notification/un message à l'aide du jeton Firebase du client. Remarque qu'en utilisant Firebase Console, je peux envoyer le message au client.

Pour l'application client, j'ai effectué les opérations suivantes:

  1. FireBase clonée messaging application de démarrage rapide à partir d’ici - https://github.com/firebase/quickstart-Android/tree/master/messaging - qui est déjà configuré avec les dépendances de Firebase et tel. Chargement de l'application clonée dans Android Studio.
  2. À l'aide de la console Firebase, créez un nouveau projet appelé My Notification Client Et ajoutez une application utilisant com.google.firebase.quickstart.fcm Comme nom de package de l'application Android.
  3. Téléchargé le fichier google-services.json Pour l'application Android ajoutée au projet nouvellement créé, copié dans le dossier messaging/app/ Et synchronisé avec les fichiers Grade de l'intérieur Android Studio.
  4. Création d'un émulateur et exécution de l'application depuis Android Studio. Une fois l'application chargée dans l'émulateur, cliquez sur le bouton Log Token Pour capturer le jeton Firebase du client dans l'onglet Android Monitor De Android Studio.
  5. À l'aide de la console Firebase, sélectionnez le projet nouvellement créé My Notification Client, Cliquez sur le lien Notifications du volet de gauche et envoyez une notification au périphérique en collant le jeton Firebase capturé à l'étape précédente.

Cela a très bien fonctionné! L'étape suivante consistait à utiliser une simple Java) distincte (qui deviendrait éventuellement un serveur de notification) pour envoyer la notification au client au lieu d'utiliser la console Firebase.

Pour ce faire, j'ai suivi les étapes décrites ici: https://firebase.google.com/docs/server/setup#prerequisites . Plus précisément, voici les étapes que j'ai effectuées:

  1. Création d'un nouveau projet appelé My Notification Server Dans la console Firebase.
  2. L’utilisation de Settings > Permissions Dans la console Firebase a créé un nouveau compte de service et téléchargé le fichier serviceAccountCredentials.json.
  3. Création d'un nouveau projet maven dans Eclipse et ajout des dépendances suivantes dans pom.xml:
    <dependency>
      <groupId>com.google.gcm</groupId>
      <artifactId>gcm-server</artifactId>
      <version>1.0.0</version>
    </dependency>
    <dependency>
      <groupId>com.googlecode.json-simple</groupId>
      <artifactId>json-simple</artifactId>
      <version>1.1.1</version>
    </dependency>
    <dependency>
      <groupId>com.google.firebase</groupId>
      <artifactId>firebase-server-sdk</artifactId>
      <version>3.0.0</version>
    </dependency>
  1. Ensuite, j'ai étendu com.google.Android.gcm.sender.Sender Pour créer FCMSender et substituer la méthode protégée getConnection(String url) pour utiliser le nouveau point de terminaison FCM, comme indiqué ci-dessous:

    class FCMSender extends Sender {
    
        public FCMSender(String key) {
            super(key);
        }
    
        @Override
        protected HttpURLConnection getConnection(String url) throws IOException {
            String fcmUrl = "https://fcm.googleapis.com/fcm/send";
            return (HttpURLConnection) new URL(fcmUrl).openConnection();
        }
    }
    
  2. La méthode main() de mon Java) ressemble à ceci:

    public static void main(String[] args) {
        // Obtain serverKey from Project Settings -> Cloud Messaging tab
        // for "My Notification Client" project in Firebase Console.
        String serverKey = <get_server_key_from_firebase_console>;
        Thread t = new Thread() {
            public void run(){ 
                try {
                    Sender sender = new FCMSender(serverKey);
                    Message message = new Message.Builder()
                                      .collapseKey("message")
                                      .timeToLive(3)
                                      .delayWhileIdle(true)
                                      .addData("message", "Notification from Java application");
                                      .build();  
    
                    // Use the same token(or registration id) that was earlier
                    // used to send the message to the client directly from
                    // Firebase Console's Notification tab.
                    Result result = sender.send(message,
                "APA91bFfIFjSCcSiJ111rbmkpnMkZY-Ej4RCpdBZFZN_mYgfHwFlx-M1UXS5FqDBcN8x1efrS2md8L9K_E9N21qB-PIHUqQwmF4p7Y3U-86nCGH7KNkZNjjz_P_qjcTR0TOrwXMh33vp",
                        1);
                    System.out.println("Result: " + result.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            };
            t.start;
            try {
                t.join();
            }
            catch (InterruptedException iex) {
                iex.printStackTrace();
            }
        }
    

Lorsque j'exécute l'application Java, j'obtiens l'erreur MismatchSenderId. J'ai essayé de dépanner en utilisant curl comme indiqué ci-dessous, mais j'ai la même erreur:

$ skey=<obtained_from_project_settings_cloud_messaging_tab_in_firebase_console>
$ curl -X POST --header "Authorization: key=$skey" \
  --Header "Content-Type: application/json" \
  https://fcm.googleapis.com/fcm/send \
  -d "{\"to\":\"APA91bFfIFjSCcSiJ111rbmkpnMkZY-Ej4RCpdBZFZN_mYgfHwFlx-M1UXS5FqDBcN8x1efrS2md8L9K_E9N21qB-PIHUqQwmF4p7Y3U-86nCGH7KNkZNjjz_P_qjcTR0TOrwXMh33vp\",\"data\":{\"message\":\"Yellow\"}}"

{"multicast_id":7391851081942579857,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"MismatchSenderId"}]}

Au lieu d'utiliser le Server Key Indiqué dans l'onglet Project Settings > Cloud Messaging Pour le projet My Notification Server Dans Firebase Console, j'ai essayé d'utiliser le Project Number, Mais cela a causé InvalidRequestException: HTTP Status Code: 401 .

La documentation de Firebase sur les codes d'erreur indique ceci à propos de MismatchSenderId:

Expéditeur incompatible 200 + error:MismatchSenderId
Un jeton d’enregistrement est lié à un certain groupe d’expéditeurs. Lorsqu'une application cliente s'enregistre pour FCM, elle doit spécifier les expéditeurs autorisés à envoyer des messages. Vous devez utiliser l'un de ces identifiants d'expéditeur lors de l'envoi de messages à l'application cliente. Si vous passez à un autre expéditeur, les jetons d'enregistrement existants ne fonctionneront pas.

Je ne pouvais pas savoir où et comment dans la console Firebase, on peut configurer l'application Android app (qui a été ajoutée au projet My Notification Client) Pour pouvoir recevoir des messages.

Toute aide à ce sujet serait appréciée!

27
Sanjay Saxena

Je courais dans le même problème. Le problème était dans la ligne:

String serverKey = <get_server_key_from_firebase_console>;

Cette valeur doit provenir du projet d'application Android; dans ce cas, il s'agirait de "My Notification Client" et non de "My Notification Server".

6
Tahira Qader

Moi aussi, j'ai récemment commencé à utiliser Firebase, sans aucune expérience préalable de Google Cloud Messaging. Autant que je sache, il n’existe actuellement aucun SDK côté serveur pour Firebase Cloud Messaging.

Pour envoyer des notifications/messages de votre serveur d'applications à votre Mobile Client, vous devez implémenter vos propres méthodes HTTP et/ou XMPP. Voir https://firebase.google.com/docs/cloud-messaging/

Mon code de test, en utilisant HTTP:

public CompletableFuture<String> fcmTest1() {
    // https://firebase.google.com/docs/cloud-messaging/http-server-ref
    String Host = "fcm.googleapis.com";
    String requestURI = "/fcm/send";
    String CLIENT_TOKEN = "ASK_YOUR_MOBILE_CLIENT_DEV"; // https://developers.google.com/instance-id/

    CompletableFuture<String> fut = new CompletableFuture<>();
    JsonObject body = new JsonObject();
    // JsonArray registration_ids = new JsonArray();
    // body.put("registration_ids", registration_ids);
    body.put("to", CLIENT_TOKEN);
    body.put("priority", "high");
    // body.put("dry_run", true);

    JsonObject notification = new JsonObject();
    notification.put("body", "body string here");
    notification.put("title", "title string here");
    // notification.put("icon", "myicon");

    JsonObject data = new JsonObject();
    data.put("key1", "value1");
    data.put("key2", "value2");

    body.put("notification", notification);
    body.put("data", data);

    HttpClientRequest hcr = httpsClient.post(443, Host, requestURI).handler(response -> {
        response.bodyHandler(buffer -> {
            logger.debug("FcmTest1 rcvd: {}, {}", response.statusCode(), buffer.toString());
            if (response.statusCode() == 200) {
                fut.complete(buffer.toString());
            } else {
                fut.completeExceptionally(new RuntimeException(buffer.toString()));
            }
        });
    });
    hcr.putHeader("Authorization", "key=" + Utils.FIREBASE_SERVER_KEY)
        .putHeader("content-type", "application/json").end(body.encode());
    return fut;
}

note: http client et json ont été fournis par vertx ( http://vertx.io/ ), mais j'espère que le code indique clairement ce qui se passe pour que vous puissiez utiliser ce que vous voulez.

9
aes

J'ai écrit une classe FCMHelper, qui fonctionne bien et qui est simple à utiliser.

Voir ici https://github.com/MOSDEV82/fcmhelper

3
MOSDEV

J'avais besoin d'envoyer une notification FCM à partir de mon Java EE et j'ai trouvé this très utile. Cela pourrait faire gagner du temps à quelqu'un.

... Le repo github est une interface de bibliothèque pour l'API Firebase Cloud Messaging (FCM) (NB // je ne suis pas l'auteur). J'ai donc suivi les instructions du fichier readme: ajouté le fichier jar en tant que dépendance de mon projet et pouvais simplement appeler les méthodes de la bibliothèque avec les paramètres correspondants.

par exemple. Pushraven.setKey(my_key); pour définir la clé de votre serveur et

Notification raven = new Notification();
raven.title("MyTitle")
     .text("Hello World!")
     .color("#ff0000")
     .to(client_key);

construire une notification. Les instructions du repo sont plutôt claires et utiles.

3
rey_coder

Sur:

// Obtain serverKey from Project Settings -> Cloud Messaging tab // for "My Notification Server" project in Firebase Console. String serverKey = <get_server_key_from_firebase_console>;

Vous devez obtenir la clé de votre Android app.

Et merci, j'avais du mal à créer un service permettant d'envoyer/recevoir des notifications pour l'application. Vu votre question, essayé de bien faire les choses et construit la mienne. J'espère que ceci vous aidera :)

1
hcordeiro

Utilisez cet envoi de notifications Push à partir de Java.

Cadre de printemps

Comparé à d'autres projets, il n'y a que 3 classes simples avec des dépendances minimales.

https://github.com/AndreiD/testingpushnotifications

N'oubliez pas de remplacer SERVER_API_KEY et Client_Token.

PS. Written by me

0
OWADVL

J'ai eu exactement le même problème et j'ai même utilisé votre code comme test pour vérifier s'il y avait un problème avec le mien. Il s'avère que nos deux codes avaient raison. Le problème est exactement comme décrit dans la documentation Firebase:

"Erreur liée à l'expéditeur 200 +: MismatchSenderId Un jeton d'enregistrement est lié à un certain groupe d'expéditeurs. Lorsqu'une application cliente s'enregistre pour FCM, elle doit spécifier les expéditeurs autorisés à envoyer des messages. Vous devez utiliser l'un de ces ID d'expéditeur lors de l'envoi de messages. Si vous passez à un autre expéditeur, les jetons d’enregistrement existants ne fonctionneront pas. "

Le problème, c’est que ce n’est pas si clair (du moins ce n’était pas pour moi). Alors voici ce dont vous avez besoin: Sur votre application Android, vous devez recevoir la clé Firebase de l’appareil. C’est différent de ce que vous aviez pour le message Google Cloud, et par conséquent il y a le problème.

Créez simplement cette classe sur votre projet Android:

classe publique NotificacaoRegistro étend FirebaseInstanceIdService {static private String TAG = "NOTIFICACAOREGISTRO";

public NotificacaoRegistro(){
    String refreshedToken = FirebaseInstanceId.getInstance().getToken();
    Log.d(TAG, "Refreshed token: " + refreshedToken);
}
@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.

}

}

N'oubliez pas de faire les changements nécessaires sur votre manifeste Android.

  <service
            Android:name=".notificacoes.NotificacaoRegistro">
            <intent-filter>
                <action Android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
  </service>

Si vous avez juste besoin du code (pour le débogage, par exemple), vous pouvez simplement appeler votre MainActivity, dans votre méthode OnCreate

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

Mais c’est mieux, bien sûr, si vous vous en occupez correctement.

De cette façon, vous obtiendrez la clé correcte pour ce périphérique. Puis sur votre Java code d'application

   Result result = sender.send(message,
            <PUT THE VALUE OF THE REFRESHED TOKEN HERE>,
                    1);

et vous êtes tous ensemble :)

J'espère que ça aide, et désolé pour le long délai :)

à votre santé

0
Marcelo Nascimento