Подтвердить что ты не робот

Firebase Cloud Messaging из Java вместо Firebase Console

Я новичок в Firebase, и я сталкиваюсь с ошибками, такими как идентификатор отправителя mismatch и Error Authentication Error с HTTP-статусом 401, когда мое приложение Java пытается отправить уведомление/сообщение, используя токен клиента Firebase. Обратите внимание, что с помощью Firebase Console я могу отправить сообщение клиенту.

Для клиентского приложения я сделал следующее:

  1. Клонированное приложение для быстрого messaging Firebase отсюда - https://github.com/firebase/quickstart-android/tree/master/messaging - которое уже настроено с зависимостями Firebase и т.д. Загрузило клонированное приложение в Android Studio.
  2. Используя Firebase Console, вы создали новый проект под названием My Notification Client и добавили приложение, используя com.google.firebase.quickstart.fcm качестве имени пакета приложения для Android.
  3. Загруженный файл google-services.json для приложения Android добавлен во вновь созданный проект и скопировал его в папку messaging/app/ и синхронизировал его с файлами Grade из Android Studio.
  4. Создал эмулятор и запускал приложение из Android Studio. Когда приложение загрузилось в эмулятор, нажмите кнопку " Log Token, чтобы зафиксировать токен клиента Firebase на вкладке " Android Monitor " в Android Studio.
  5. Используя Firebase Console, вы выбрали недавно созданный проект " My Notification Client, щелкнули ссылку " Notifications на левой панели и отправили уведомление на устройство, вставив токен Firebase, записанный на предыдущем шаге.

Это здорово! Следующим шагом было использование отдельного простого Java-приложения (которое в конечном итоге стало сервером уведомлений) для отправки уведомления клиенту вместо использования Firebase Console.

Чтобы выполнить это, я выполнил описанные здесь шаги - https://firebase.google.com/docs/server/setup#prerequisites. В частности, это шаги, которые я выполнил:

  1. Создал новый проект под названием My Notification Server в Firebase Console.
  2. Используя " Settings > Permissions в Firebase Console, создайте новую учетную запись службы и загрузите файл serviceAccountCredentials.json.
  3. Создал новый проект maven в Eclipse и добавил следующие значения в 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. Метод 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 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"}]}

Вместо использования Server Key указанного в Project Settings > Cloud Messaging вкладка " Project Settings > Cloud Messaging " для проекта " My Notification Server " в Firebase Console, я попытался использовать Project Number но вызвал InvalidRequestException: HTTP Status Code: 401.

Firebase документация кодов ошибок говорит о MismatchSenderId:

error:MismatchSenderId Mistatched Sender 200 + error:MismatchSenderId
Маркер регистрации привязан к определенной группе отправителей. Когда клиентское приложение регистрируется для FCM, оно должно указать, какие отправители могут отправлять сообщения. Вы должны использовать один из этих идентификаторов отправителя при отправке сообщений в клиентское приложение. Если вы переключитесь на другого отправителя, существующие токены регистрации не будут работать.

Я не мог понять, где/как в Firebase Console можно настроить приложение Android (которое было включено в проект My Notification Client), чтобы получать сообщения.

Любая помощь по этому поводу была бы оценена!

4b9b3361

Ответ 1

Я столкнулся с той же проблемой. Проблема была в строке:

String serverKey = <get_server_key_from_firebase_console>;

Это значение должно исходить из проекта приложения Android; в этом случае это будет "My Notification Client", а не "My Notification Server".

Ответ 2

Я тоже недавно начал использовать Firebase без предварительного опыта в облачных сообщениях Google. AFAIK, на данный момент нет SDK на стороне сервера для Firebase Cloud Messaging.

Для отправки уведомлений/сообщений с вашего сервера приложений на мобильный клиент вам необходимо реализовать собственные методы 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/), но, надеюсь, код показывает, что происходит достаточно ясно, чтобы вы могли использовать все, что пожелаете.

Ответ 3

Я написал класс FCMHelper, который отлично работает и прост в использовании.

См. здесь https://github.com/MOSDEV82/fcmhelper

Ответ 4

Мне нужно было отправить уведомление FCM из моего приложения Java EE, и я нашел this очень полезным. Может кто-нибудь кого-нибудь спасти.

... github repo - это интерфейс библиотеки для Firebase Cloud Messaging (FCM) API (NB//Я не автор). Поэтому я выполнил инструкции в readme: добавил файл jar в качестве зависимости к моему проекту и мог просто вызвать методы библиотеки с соответствующими параметрами.

например. Pushraven.setKey(my_key);, чтобы установить ключ сервера и

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

чтобы создать уведомление. Инструкции из репо довольно ясны и полезны.

Ответ 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>;

Вы должны получить ключ для своего приложения для Android.

И спасибо, я боролся за создание сервиса для отправки/получения уведомлений для приложения. Увидел ваш вопрос, попытался исправить это и использовал для создания моего. Надеюсь, это вам поможет:)

Ответ 6

Я только что начал с FireBase, но похоже, что кто-то (Brandon Gresham) уже создал Java-интерфейс Firebase.

Вы можете проверить сторонние API для разных языков здесь: https://firebase.google.com/docs/database/rest/start

И вот Java: https://github.com/bane73/firebase4j

Большое спасибо Брэндону за то, что он посвятил ему время!

Ответ 7

У меня была такая же проблема, и я даже использовал ваш код в качестве теста, чтобы проверить, что что-то не так с моим. Оказывается, оба наших кода были правильными. Проблема будет такой же, как описано в документах Firebase:

"Ошибка Mismatched Sender 200 +: MismatchSenderId Регистрационный токен привязан к определенной группе отправителей. Когда клиентское приложение регистрируется для FCM, оно должен указать, какие отправители могут отправлять сообщения. Вы должны использовать один этих идентификаторов отправителя при отправке сообщений в клиентское приложение. Если вы переключитесь другому отправителю, существующие регистрационные токены не будут работать. "

Проблема в том, что это не так понятно (по крайней мере, для меня это не было). Итак, вот что вам нужно: в вашем приложении Android вам нужно будет получить ключ Firebase для устройства. Это не то же самое, что вы использовали для Google Cloud Message, и, следовательно, есть проблема.

Просто создайте этот класс в своем проекте Android:

открытый класс 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 servers.

}

}

Не забудьте внести необходимые изменения в свой AndroidManifest

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

Если вам просто нужен код (например, для отладки), вы можете просто вызвать MainActivity в методе OnCreate

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

Но лучше, если вы позаботитесь об этом правильно.

Таким образом вы получите правильный ключ для этого устройства. Затем в коде Java-приложения

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

и вы все настроены:)

Надеюсь, что это поможет, и извините за долгую задержку:)

веселит

Ответ 8

Используйте эту отправку push-уведомлений из java.

Spring Framework

По сравнению с другими проектами существует только 3 простых класса с минимальными зависимостями.

https://github.com/AndreiD/testingpushnotifications

Не забудьте заменить SERVER_API_KEY и Client_Token.

PS. Написано мной