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

新手上路,请多包涵

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

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

  1. 克隆的 Firebase messaging 此处的快速启动应用程序 -- 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/ 文件夹并与—8dc7c69db1b10e462c631-f669-93中的Grade文件 Android Studio
  4. 创建了一个模拟器并从 Android Studio 中运行应用程序。当应用程序加载到模拟器中时,单击 Log Token 按钮以在 Android Monitor 选项卡中捕获客户端的 Firebase 令牌 Android Studio .
  5. 使用 Firebase 控制台,选择新创建的项目 My Notification Client ,单击左侧窗格中的 Notifications 链接,并通过粘贴在上一步中捕获的 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();
       }
   }

  1. 我的 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"}]}

Instead of using the Server Key listed on Project Settings > Cloud Messaging tab for My Notification Server project in Firebase Console, I tried using the Project Number but that caused InvalidRequestException: HTTP Status Code: 401

错误代码的 Firebase 文档是关于 MismatchSenderId 的:

发件人不匹配 200 + error:MismatchSenderId

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

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

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

原文由 Sanjay Saxena 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 545
2 个回答

我遇到了同样的问题。问题在于:

 String serverKey = <get_server_key_from_firebase_console>;

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

原文由 Tahira Qader 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

要将通知/消息从您的应用服务器发送到您的移动客户端,您需要实现您自己的 HTTP 和/或 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/ ) 提供,但希望代码能够清楚地显示发生了什么,以便您可以使用任何您想要的。

原文由 aes 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题