简体   繁体   English

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

[英]Firebase Cloud Messaging notification from Java instead of Firebase Console

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. 我是Firebase的新手,当我的Java应用程序尝试使用客户端的Firebase令牌发送通知/消息时,我遇到错误,例如错误的发件人ID和HTTP状态401的身份验证错误。 Note that using Firebase Console, I am able to send the message to the client. 请注意,使用Firebase控制台,我可以将消息发送到客户端。

For the client app, I did the following: 对于客户端应用程序,我执行了以下操作:

  1. Cloned Firebase messaging quickstart app from here -- https://github.com/firebase/quickstart-android/tree/master/messaging -- which is already setup with Firebase dependencies and such. 克隆Firebase messaging快速入门应用程序 - https://github.com/firebase/quickstart-android/tree/master/messaging - 已经设置了Firebase依赖等。 Loaded the cloned app in Android Studio . Android Studio加载了克隆的应用程序。
  2. Using Firebase Console, created a new project called My Notification Client and added an app using com.google.firebase.quickstart.fcm as the package name of the Android app. 使用Firebase控制台,创建了一个名为“ My Notification Client的新项目,并使用com.google.firebase.quickstart.fcm添加了一个应用,作为Android应用的包名称。
  3. Downloaded google-services.json file 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 . 下载了添加到新创建项目的Android应用的google-services.json文件,并将其复制到messaging/app/文件夹,并与Android Studio成绩文件同步。
  4. Created an emulator and ran the app from within Android Studio . 创建了一个模拟器并在Android Studio运行应用程序。 When the app got loaded in the emulator, clicked the Log Token button to capture the client's Firebase token in the Android Monitor tab in Android Studio . 当应用程序加载到模拟器中时,单击“ Log Token按钮以在Android StudioAndroid Monitor选项卡中捕获客户端的Firebase标记。
  5. Using Firebase Console, selected the newly created project My Notification Client , clicked the Notifications link from the left pane, and sent a notification to the device by pasting the Firebase token captured in the previous step. 使用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 . 为此,我按照此处列出的步骤进行了操作 - https://firebase.google.com/docs/server/setup#prerequisites Specifically, these are the steps that I performed: 具体来说,这些是我执行的步骤:

  1. Created a new project called My Notification Server in Firebase Console. 在Firebase控制台中创建了一个名为My Notification Server的新项目。
  2. Using Settings > Permissions in Firebase Console, created a new service account and downloaded the serviceAccountCredentials.json file. 使用Firebase控制台中的Settings > Permissions ,创建新服务帐户并下载serviceAccountCredentials.json文件。
  3. Created a new maven project in Eclipse and added the following dependencies in pom.xml: 在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.Sender to create FCMSender and override protected method getConnection(String url) to use the new FCM endpoint as shown below: 然后,我扩展了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. The main() method of my Java application looks like this: 我的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(); } } 

When I run the Java application, I get MismatchSenderId error. 当我运行Java应用程序时,我收到MismatchSenderId错误。 I tried troubleshooting using curl as shown below but got the same error: 我尝试使用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控制台中My Notification Server项目的Project Settings > Cloud Messaging选项卡上列出的Server Key ,而是尝试使用Project Number但导致InvalidRequestException: HTTP Status Code: 401

Firebase documentation of the error codes says this about MismatchSenderId : 错误代码的Firebase文档说明了MismatchSenderId

Mismatched Sender 200 + error:MismatchSenderId 不匹配的发件人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. 当客户端应用程序注册FCM时,它必须指定允许哪些发件人发送消息。 You should use one of those sender IDs when sending messages to the client app. 在向客户端应用程序发送消息时,您应该使用其中一个发件人ID。 If you switch to a different sender, the existing registration tokens won't work. 如果您切换到其他发件人,现有的注册令牌将无法使用。

I could not figure out where/how in Firebase Console one can configure the Android app(which was aded to the My Notification Client project) to be able to receive messages. 我无法弄清楚Firebase控制台在哪里/如何配置Android应用程序(与My Notification Client项目相关)以便能够接收消息。

Any help on this, would be appreciated! 对此有任何帮助,将不胜感激!

I too have recently started using Firebase, with no prior experience in Google Cloud Messaging. 我最近也开始使用Firebase,没有谷歌云消息传递方面的经验。 AFAIK, there's no server side SDK for Firebase Cloud Messaging, currently. 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. 要将通知/消息从App Server发送到Mobile Client,您需要实现自己的HTTP和/或XMPP方法。 See https://firebase.google.com/docs/cloud-messaging/ 请参阅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/ )提供的,但希望代码能够清楚地显示出足够清晰的内容,以便您可以使用任何您想要的内容。

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; 此值应来自Android应用程序项目; in this case it would be "My Notification Client" and not "My Notification Server". 在这种情况下,它将是“我的通知客户端”而不是“我的通知服务器”。

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

I needed to send FCM notification from my java EE application and I found this very helpful. 我需要从我的java EE应用程序发送FCM通知,我发现非常有用。 Might save someone some time. 可能会节省一些时间。

...The github repo is a library interface for Firebase Cloud Messaging (FCM) API (NB// I am not the author). ... github repo是Firebase云消息传递(FCM)API的库接口(NB //我不是作者)。 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. 所以我按照自述文件中的说明操作:将jar文件添加为我的项目的依赖项,并且可以使用各自的参数调用库方法。

eg Pushraven.setKey(my_key); 例如Pushraven.setKey(my_key); to set your server key and 设置您的服务器密钥和

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. 回购的说明非常明确且有用。

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>;

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 :) 希望对你有帮助 :)

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 . 这就是您需要的:在您的Android应用程序中,您需要接收设备的Firebase密钥。 It is not the same you used to have for the Google Cloud Message, and hence there´s the problem. 它与您以前用于Google Cloud Message的方式不同,因此存在问题。

Just create this class on your Android project: 只需在Android项目上创建此类:

public class NotificacaoRegistro extends FirebaseInstanceIdService { static private String TAG = "NOTIFICACAOREGISTRO"; public class 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 干杯

Use this sending push notifications from java. 使用来自java的此发送推送通知。

Spring Framework Spring框架

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。由我写的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM