【问题标题】:Firebase Cloud Messaging notification from Java instead of Firebase Console来自 Java 而不是 Firebase 控制台的 Firebase 云消息传递通知
【发布时间】:2016-09-22 10:22:52
【问题描述】:

我是 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. 为添加到新创建项目的 Android 应用下载了 google-services.json 文件,并将其复制到 messaging/app/ 文件夹并与 Android Studio 中的成绩文件同步。
  4. 创建了一个模拟器并从Android Studio 中运行该应用程序。当应用程序在模拟器中加载时,单击Log Token 按钮以在Android StudioAndroid Monitor 选项卡中捕获客户端的Firebase 令牌。
  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();
        }
    }
    
  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"}]}

我尝试使用 Project Number 而不是在 Firebase 控制台中的 My Notification Server 项目中使用 Project Settings &gt; Cloud Messaging 选项卡上列出的 Server Key,但这会导致 InvalidRequestException: HTTP Status Code: 401

错误代码的 Firebase 文档说明了 MismatchSenderId

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

我不知道在 Firebase 控制台中的何处/如何配置 Android 应用(已添加到 My Notification Client 项目)以能够接收消息。

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

【问题讨论】:

标签: java firebase firebase-cloud-messaging


【解决方案1】:

我最近也开始使用 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/) 提供,但希望代码能够清楚地显示正在发生的事情,以便您可以随意使用。

【讨论】:

  • 有服务器端sdk firebase-server-sdk
  • @Hamedz 不用于我能找到的 FCM。
  • firebase-server-sdk 已弃用,取而代之的是 firebase-admin-sdk,并在后者上引用 Google 文档:“Firebase Admin Java SDK 当前没有 FCM API。如果您想从非 Node.js 服务器发送消息,您应该使用 HTTP 或 XMPP API,如“关于 Firebase 云消息服务器”中所述。 FCM 是 Firebase 云消息传递。
  • @aes 如何通过发送自定义字段信息到firebase获取registrationToken?
【解决方案2】:

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

String serverKey = <get_server_key_from_firebase_console>;

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

【讨论】:

  • 你是对的!我根本不需要“我的通知服务器”项目。使用“我的通知客户端”中的服务器密钥,我能够使其工作。
  • 大多数时候我们使用的授权密钥可能是错误的。检查dev.tapjoy.com/faq/how-to-find-sender-id-and-api-key-for-gcm 以查看您是否使用了正确的密钥。我在为 firebase 选择 API 密钥时也感到困惑我们必须在 firebase 设置下的 Cloud 消息选项卡中使用 SENDER ID - API KEY 对。即转到 firebase App--> Go to app setting --> Cloud Messaging 在那里你可以找到 Sender Id API key 和这个 API key 你可以用来发送 FCM。
【解决方案3】:

我写了一个 FCMHelper 类,效果很好,使用也很简单。

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

【讨论】:

  • 谢谢!!它对我有用。能够将 FCM 从 Web 服务发送到 Android 设备。
  • 谢谢你,节省了一些时间,简单优雅,切中要害,效果很好。
【解决方案4】:

我需要从我的 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);

建立一个通知。来自 repo 的说明非常清晰且很有帮助。

【讨论】:

  • 请在您的答案中添加更多信息,至少是对链接的描述以及它如何帮助解决问题...
  • 好的。 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); 构建通知。来自 repo 的说明非常清晰和有用。
  • 这样更好 :-) 我建议您将该评论移至您的答案中。
【解决方案5】:

开启:

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

您必须获取您的安卓应用程序的密钥。

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

【讨论】:

    【解决方案6】:

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

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

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

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

    公共类 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);
    

    你们都准备好了:)

    希望这会有所帮助,对长时间的延迟表示歉意:)

    干杯

    【讨论】:

      【解决方案7】:

      使用这个从 java 发送推送通知。

      Spring 框架

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

      https://github.com/AndreiD/testingpushnotifications

      记得替换 SERVER_API_KEY 和 Client_Token。

      【讨论】:

        猜你喜欢
        • 2017-05-05
        • 2022-07-20
        • 2020-06-28
        • 2016-09-19
        • 2016-12-25
        • 2016-12-02
        • 2016-12-13
        • 2021-07-22
        • 2017-07-31
        相关资源
        最近更新 更多