来自 Java 而非 Firebase 控制台的 Firebase 云消息传递通知

Firebase Cloud Messaging notification from Java instead of Firebase Console

我是 Firebase 的新手,当我的 Java 应用程序尝试发送 notification/message使用客户端的 Firebase 令牌。请注意,使用 Firebase 控制台,我可以将消息发送到客户端。

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

  1. 从这里克隆的 Firebase messaging 快速启动应用程序 -- https://github.com/firebase/quickstart-android/tree/master/messaging -- 它已经设置了 Firebase 依赖项等。在 Android Studio.
  2. 中加载了克隆的应用程序
  3. 使用 Firebase 控制台,创建了一个名为 My Notification Client 的新项目,并使用 com.google.firebase.quickstart.fcm 作为 Android 应用程序包名称添加了一个应用程序。
  4. 已将 Android 应用程序的 google-services.json 文件添加到新创建的项目并将其复制到 messaging/app/ 文件夹并与 [=16= 中的成绩文件同步].
  5. Android Studio 中创建了模拟器和 运行 应用程序。在模拟器中加载应用程序后,单击 Log Token 按钮以在 Android StudioAndroid Monitor 选项卡中捕获客户端的 Firebase 令牌。
  6. 使用 Firebase 控制台,选择新创建的项目 My Notification Client,单击左侧窗格中的 Notifications link,并通过粘贴捕获的 Firebase 令牌向设备发送通知在上一步中。

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

为实现这一点,我遵循了此处概述的步骤 -- https://firebase.google.com/docs/server/setup#prerequisites。具体来说,这些是我执行的步骤:

  1. 在 Firebase 控制台中创建了一个名为 My Notification Server 的新项目。
  2. 在 Firebase 控制台中使用 Settings > Permissions,创建了一个新的服务帐户并下载了 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. 然后,我扩展 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. 我的 Java 应用程序的 main() 方法如下所示:

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

当我 运行 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"}]}

我没有使用 Firebase 控制台中 My Notification Server 项目的 Project Settings > Cloud Messaging 选项卡上列出的 Server Key,而是尝试使用 Project Number,但这导致了 InvalidRequestException: HTTP Status Code: 401 .

错误代码的 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.

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

如有任何帮助,我们将不胜感激!

开启:

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

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

谢谢,我一直在努力为应用程序构建 send/receive 通知服务。看到你的问题,试图把它弄对,并用来构建我的。希望这对你有帮助:)

我最近也开始使用 Firebase,之前没有使用 Google 云消息传递的经验。据我所知,目前没有用于 Firebase 云消息传递的服务器端 SDK。

要将 notifications/messages 从您的应用服务器发送到您的移动客户端,您需要实现自己的 HTTP and/or XMPP 方法。参见 https://firebase.google.com/docs/cloud-messaging/

我的测试代码,使用 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;
}

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

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

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

问题是,这不是很清楚(至少对我来说不是)。 所以这就是您需要的:在您的 Android 应用程序中,您需要接收设备的 Firebase 密钥。它与您以前使用的 Google 云消息不同,因此存在问题。

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

public class NotificacaoRegistro 扩展了 FirebaseInstanceIdService { 静态私有字符串 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.

}

}

不要忘记对您的 AndroidManifest

进行必要的更改
  <service
            android:name=".notificacoes.NotificacaoRegistro">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
            </intent-filter>
  </service>

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

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

但是,如果您处理得当,那就更好了。

这样您就可以获得该设备的正确密钥。然后在您的 Java 申请代码

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

一切就绪:)

希望这对您有所帮助,抱歉耽搁了这么久:)

干杯

我 运行 遇到了同样的问题。问题出在行中:

String serverKey = <get_server_key_from_firebase_console>;

这个值应该来自Android应用项目;在这种情况下,它将是 "My Notification Client" 而不是 "My Notification Server".

我写了一个 FCMHelper Class,它工作正常并且易于使用。

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

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

Spring 框架

与其他项目相比,只有 3 个简单的 类 且依赖性极低。

https://github.com/AndreiD/testingpushnotifications

记得替换 SERVER_API_KEY 和 Client_Token。

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

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

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

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

建立通知。回购协议中的说明非常清晰和有用。