来自 Java 而不是 Firebase 控制台的 Firebase 云消息通知

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37426542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:19:27  来源:igfitidea点击:

Firebase Cloud Messaging notification from Java instead of Firebase Console

javafirebasefirebase-cloud-messaging

提问by Sanjay Saxena

I am new to Firebase and I am running into errors such as mismatch sender id and Authentication Error with HTTP status 401 when my Java application tries to send a notification/message using the client's Firebase token. Note that using Firebase Console, I am able to send the message to the client.

我是 Firebase 的新手,当我的 Java 应用程序尝试使用客户端的 Firebase 令牌发送通知/消息时,我遇到了错误,例如不匹配的发件人 ID 和 HTTP 状态 401 的身份验证错误。请注意,使用 Firebase 控制台,我可以将消息发送给客户端。

For the client app, I did the following:

对于客户端应用程序,我执行了以下操作:

  1. Cloned Firebase messagingquickstart app from here -- https://github.com/firebase/quickstart-android/tree/master/messaging-- which is already setup with Firebase dependencies and such. Loaded the cloned app in Android Studio.
  2. Using Firebase Console, created a new project called My Notification Clientand added an app using com.google.firebase.quickstart.fcmas the package name of the Android app.
  3. Downloaded google-services.jsonfile for the Android app added to the newly created project and copied it to the messaging/app/folder and sync'd with Grade files from within Android Studio.
  4. Created an emulator and ran the app from within Android Studio. When the app got loaded in the emulator, clicked the Log Tokenbutton to capture the client's Firebase token in the Android Monitortab in Android Studio.
  5. Using Firebase Console, selected the newly created project My Notification Client, clicked the Notificationslink from the left pane, and sent a notification to the device by pasting the Firebase token captured in the previous step.
  1. messaging从这里克隆的 Firebase快速入门应用程序 -- https://github.com/firebase/quickstart-android/tree/master/messaging-- 已经设置了 Firebase 依赖项等。在Android Studio.
  2. 使用 Firebase 控制台,创建了一个名为的新项目,My Notification Client并添加了一个com.google.firebase.quickstart.fcm用作 Android 应用程序包名称的应用程序。
  3. 已下载google-services.json的 Android 应用程序文件已添加到新创建的项目中,并将其复制到messaging/app/文件夹中,并与Android Studio.
  4. 创建了一个模拟器并从Android Studio. 当应用程序在模拟器中加载后,单击Log Token按钮以在 中的Android Monitor选项卡中捕获客户端的 Firebase 令牌Android Studio
  5. 使用 Firebase 控制台,选择新创建的项目My Notification Client,单击Notifications左侧窗格中的链接,然后通过粘贴上一步中捕获的 Firebase 令牌向设备发送通知。

This worked great! The next step was to to use a separate simple Java application (which would eventually become a notification server) to send the notification to the client instead of using Firebase Console.

这很好用!下一步是使用单独的简单 Java 应用程序(最终将成为通知服务器)将通知发送到客户端,而不是使用 Firebase 控制台。

To accomplish this, I followed the steps outlined here -- https://firebase.google.com/docs/server/setup#prerequisites. Specifically, these are the steps that I performed:

为此,我按照此处概述的步骤进行操作 - https://firebase.google.com/docs/server/setup#prerequisites。具体来说,这些是我执行的步骤:

  1. Created a new project called My Notification Serverin Firebase Console.
  2. Using Settings > Permissionsin Firebase Console, created a new service account and downloaded the serviceAccountCredentials.jsonfile.
  3. Created a new maven project in Eclipse and added the following dependencies in pom.xml:
  1. My Notification Server在 Firebase 控制台中创建了一个名为的新项目。
  2. Settings > Permissions在 Firebase 控制台中使用,创建一个新的服务帐户并下载serviceAccountCredentials.json文件。
  3. 在Eclipse中新建了一个maven项目,在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. Then, I extended com.google.android.gcm.sender.Senderto create FCMSenderand override protected method getConnection(String url)to use the new FCM endpoint as shown below:

    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. The main()method of my Java application looks like this:

    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();
            }
        }
    
  1. 然后,我扩展com.google.android.gcm.sender.Sender到创建FCMSender和覆盖受保护的方法getConnection(String url)以使用新的 FCM 端点,如下所示:

    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. main()我的 Java 应用程序的方法如下所示:

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

When I run the Java application, I get MismatchSenderIderror. I tried troubleshooting using curlas shown below but got the same error:

当我运行 Java 应用程序时,MismatchSenderId出现错误。我尝试使用curl如下所示进行故障排除,但得到了相同的错误:

$ 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"}]}

Instead of using the Server Keylisted on Project Settings > Cloud Messagingtab for My Notification Serverproject in Firebase Console, I tried using the Project Numberbut that caused InvalidRequestException: HTTP Status Code: 401.

我没有使用 Firebase 控制台中项目的选项卡上Server Key列出的列表,而是尝试使用但导致.Project Settings > Cloud MessagingMy Notification ServerProject NumberInvalidRequestException: HTTP Status Code: 401

Firebase documentation of the error codes says this about MismatchSenderId:

错误代码的 Firebase 文档说明了以下内容MismatchSenderId

Mismatched Sender 200 + error:MismatchSenderId
A registration token is tied to a certain group of senders. When a client app registers for FCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app. If you switch to a different sender, the existing registration tokens won't work.

不匹配的发件人 200 +error:MismatchSenderId
注册令牌与特定的发件人组相关联。当客户端应用程序注册 FCM 时,它必须指定允许哪些发件人发送消息。向客户端应用程序发送消息时,您应该使用这些发件人 ID 之一。如果您切换到不同的发件人,现有的注册令牌将不起作用。

I could not figure out where/how in Firebase Console one can configure the Android app(which was aded to the My Notification Clientproject) to be able to receive messages.

我无法弄清楚在 Firebase 控制台中的何处/如何配置 Android 应用程序(已添加到My Notification Client项目中)以能够接收消息。

Any help on this, would be appreciated!

对此有任何帮助,将不胜感激!

采纳答案by Tahira Qader

I was running into the same issue. The problem was in the line:

我遇到了同样的问题。问题出在这一行:

String serverKey = <get_server_key_from_firebase_console>;

This value should come from the Android app project; in this case it would be "My Notification Client" and not "My Notification Server".

这个值应该来自 Android 应用项目;在这种情况下,它将是“我的通知客户端”而不是“我的通知服务器”。

回答by hcordeiro

On:

在:

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

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

You must obtain the key for your android app.

您必须为您的 android 应用程序获取密钥。

And thank you, I was struggling to build a service to send/receive notifications for the app. Saw your question, tried to get it right, and used to build mine. Hope this will help you :)

谢谢,我正在努力构建一个服务来发送/接收应用程序的通知。看到你的问题,试图把它弄对,并用来建造我的。希望能帮到你 :)

回答by aes

I too have recently started using Firebase, with no prior experience in Google Cloud Messaging. AFAIK, there's no server side SDK for Firebase Cloud Messaging, currently.

我最近也开始使用 Firebase,之前没有使用过 Google Cloud Messaging。AFAIK,目前没有用于 Firebase 云消息传递的服务器端 SDK。

To send notifications/messages from your App Server to your Mobile Client, you need to implement your own HTTP and/or XMPP methods. See https://firebase.google.com/docs/cloud-messaging/

要将通知/消息从您的应用服务器发送到您的移动客户端,您需要实现自己的 HTTP 和/或 XMPP 方法。请参阅https://firebase.google.com/docs/cloud-messaging/

My testing code, using HTTP:

我的测试代码,使用 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 and json were provided by vertx (http://vertx.io/), but hopefully the code shows what's going on clear enough so you can use whatever you wish.

注意:http 客户端和 json 由 vertx ( http://vertx.io/) 提供,但希望代码能够清楚地显示正在发生的事情,以便您可以使用任何您想要的。

回答by Marcelo Nascimento

I had the exacly same problem, and even used your code as a test to check if there was something wrong with mine. It turns out that both of our codes were right. The problem is exacly as described on Firebase docs:

我遇到了完全相同的问题,甚至使用您的代码作为测试来检查我的代码是否有问题。事实证明,我们的两个代码都是正确的。问题完全如 Firebase 文档中所述:

"Mismatched Sender 200 + error:MismatchSenderId A registration token is tied to a certain group of senders. When a client app registers for FCM, it must specify which senders are allowed to send messages. You should use one of those sender IDs when sending messages to the client app. If you switch to a different sender, the existing registration tokens won't work."

“不匹配的发件人 200 + 错误:MismatchSenderId 注册令牌与特定的发件人组相关联。当客户端应用程序注册 FCM 时,它必须指定允许哪些发件人发送消息。您应该在发送消息时使用这些发件人 ID 之一到客户端应用程序。如果您切换到不同的发件人,现有的注册令牌将不起作用。”

Problem is, that′s not that clear (at least wasn′t for me). So here's what you need: On your Android application, you'll need to receive the Firebase key for the device . It is not the same you used to have for the Google Cloud Message, and hence there′s the problem.

问题是,这不是那么清楚(至少对我来说不是)。所以这就是您需要的:在您的 Android 应用程序上,您需要接收设备的 Firebase 密钥。它与您过去使用的 Google Cloud Message 不同,因此存在问题。

Just create this class on your Android project:

只需在您的 Android 项目上创建此类:

public class NotificacaoRegistro extends FirebaseInstanceIdService { static private String TAG = "NOTIFICACAOREGISTRO";

公共类 NotificacaoRegistro 扩展 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.

}

}

}

Don't forget to make the necessary changes on your AndroidManifest

不要忘记对您的 AndroidManifest 进行必要的更改

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

If you just need the code (for debugging, for example) you can just call on your MainActivity, in your OnCreate method

如果您只需要代码(例如用于调试),您可以在 OnCreate 方法中调用 MainActivity

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

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

But it′s better, ofc if you take care of that properly.

但是,如果您妥善处理它,那就更好了。

That way you'll get the correct key for that device. Then on your Java application code

这样,您将获得该设备的正确密钥。然后在您的 Java 应用程序代码上

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

and you are all set :)

你已经准备好了:)

Hope this helps, and sorry about the long delay :)

希望这会有所帮助,并对长时间的延迟感到抱歉:)

cheers

干杯

回答by MOSDEV

I wrote an FCMHelper Class, that works fine and is simple to use.

我写了一个 FCMHelper 类,它运行良好且易于使用。

See here https://github.com/MOSDEV82/fcmhelper

看这里https://github.com/MOSDEV82/fcmhelper

回答by OWADVL

Use this sending push notifications from java.

使用此从 java 发送推送通知。

Spring Framework

弹簧框架

Compared to other projects there are just 3 simple classes with minimal dependencies.

与其他项目相比,只有 3 个具有最少依赖关系的简单类。

https://github.com/AndreiD/testingpushnotifications

https://github.com/AndreiD/testingpushnotifications

Remember to replace the SERVER_API_KEY and the Client_Token.

请记住替换 SERVER_API_KEY 和 Client_Token。

PS. Written by me

附注。 我写的

回答by rey_coder

I needed to send FCM notification from my java EE application and I found thisvery helpful. Might save someone some time.

我需要从我的 java EE 应用程序发送 FCM 通知,我发现非常有帮助。可能会节省一些时间。

...The github repo is a library interface for Firebase Cloud Messaging (FCM) API (NB// I am not the author). So I followed instructions in the readme: added the jar file as a dependency to my project and could just invoke the library methods with respective parameters.

...github repo 是 Firebase Cloud Messaging (FCM) API 的库接口(注意//我不是作者)。所以我按照自述文件中的说明:将 jar 文件作为依赖项添加到我的项目中,并且可以使用相应的参数调用库方法。

e.g. Pushraven.setKey(my_key);to set your server key and

例如Pushraven.setKey(my_key);设置您的服务器密钥和

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

to build a notification. The instructions from the repo are pretty much clear and helpful.

构建通知。来自 repo 的说明非常清晰和有用。