30

Firebase は初めてで、Java アプリケーションがクライアントの Firebase トークンを使用して通知/メッセージを送信しようとすると、送信者 ID の不一致や HTTP ステータス 401 の認証エラーなどのエラーが発生します。Firebase コンソールを使用すると、メッセージをクライアントに送信できることに注意してください。

クライアント アプリでは、次のことを行いました。

  1. ここから複製されたFirebasemessagingクイックスタート アプリ -- https://github.com/firebase/quickstart-android/tree/master/messaging -- Firebase の依存関係などで既にセットアップされています。で複製されたアプリをロードしましたAndroid Studio
  2. Firebase コンソールを使用して、という名前の新しいプロジェクトを作成し、Android アプリのパッケージ名としてMy Notification Client使用するアプリを追加しました。com.google.firebase.quickstart.fcm
  3. google-services.json新しく作成されたプロジェクトに追加された Android アプリ用のダウンロードファイルをmessaging/app/フォルダーにコピーし、 内のグレード ファイルと同期しますAndroid Studio
  4. エミュレーターを作成し、 内からアプリを実行しましたAndroid Studio。アプリがエミュレーターに読み込まれたら、ボタンをクリックして、 のタブでLog Tokenクライアントの Firebase トークンを取得します。Android MonitorAndroid Studio
  5. Firebase コンソールを使用して、新しく作成されたプロジェクトを選択し、左側のペインからリンクをMy Notification ClientクリックしNotificationsて、前の手順で取得した Firebase トークンを貼り付けてデバイスに通知を送信しました。

これはうまくいきました!次のステップは、Firebase コンソールを使用する代わりに、別の単純な Java アプリケーション (最終的に通知サーバーになる) を使用してクライアントに通知を送信することでした。

これを達成するために、ここで概説されている手順に従いました -- https://firebase.google.com/docs/server/setup#prerequisites。具体的には、これらは私が実行した手順です。

  1. My Notification ServerFirebase Console で呼び出される新しいプロジェクトを作成しました。
  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. 次に、以下に示すように、新しい FCM エンドポイントを使用するために保護されたメソッドcom.google.android.gcm.sender.Senderを作成FCMSenderおよびオーバーライドするように拡張しました。getConnection(String url)

    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 コンソールのプロジェクトのServer KeyリストにあるProject Settings > Cloud Messagingタブを使用する代わりに、を使用してみましたが、それが原因でした。My Notification ServerProject NumberInvalidRequestException: HTTP Status Code: 401

エラーコードのFirebaseドキュメントには、次のことが記載されていますMismatchSenderId

送信者の不一致 200 +error:MismatchSenderId
登録トークンが特定の送信者グループに関連付けられています。クライアント アプリは、FCM に登録するときに、メッセージの送信を許可する送信者を指定する必要があります。メッセージをクライアント アプリに送信するときは、これらの送信者 ID のいずれかを使用する必要があります。別の送信者に切り替えると、既存の登録トークンは機能しなくなります。

My Notification Clientメッセージを受信できるように、Firebase Console で Android アプリ (プロジェクトに追加されたもの) を構成できる場所/方法がわかりませんでした。

これについて何か助けていただければ幸いです!

4

7 に答える 7

10

私も最近 Firebase を使い始めましたが、Google Cloud Messaging の経験はありません。現在、Firebase Cloud Messaging 用のサーバー側 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/ ) によって提供されましたが、コードが何が起こっているかを十分に明確に示しているため、好きなものを使用できます。

于 2016-06-01T09:31:27.130 に答える
6

私は同じ問題に遭遇していました。問題は次の行にありました。

String serverKey = <get_server_key_from_firebase_console>;

この値は、Android アプリ プロジェクトから取得する必要があります。この場合、「My Notification Server」ではなく「My Notification Client」になります。

于 2016-09-19T20:42:42.967 に答える
0

私はまったく同じ問題を抱えており、あなたのコードをテストとして使用して、私のコードに問題があるかどうかを確認しました。どちらのコードも正しか​​ったことがわかりました。この問題は、Firebase docs で説明されているとおりです。

"Mismatched Sender 200 + error:MismatchSenderId 登録トークンは特定の送信者グループに関連付けられています。クライアント アプリが FCM に登録するときは、メッセージの送信を許可する送信者を指定する必要があります。メッセージを送信するときは、これらの送信者 ID のいずれかを使用する必要があります。クライアント アプリに送信します。別の送信者に切り替えると、既存の登録トークンは機能しません。」

問題は、それが明確ではないことです (少なくとも私にはわかりませんでした)。必要なものは次のとおりです。Android アプリケーションでは、デバイスの Firebase キーを受け取る必要があります。これは、Google クラウド メッセージで使用していたものとは異なるため、問題があります。

Android プロジェクトでこのクラスを作成するだけです。

public class NotificacaoRegistro extends 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.

}

}

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

そして、あなたはすべて設定されています:)

これがお役に立てば幸いです。長い遅延について申し訳ありません:)

乾杯

于 2016-09-16T18:56:45.210 に答える
0

これを使用して、Java からプッシュ通知を送信します。

春のフレームワーク

他のプロジェクトと比較して、依存関係が最小限の単純なクラスが 3 つしかありません。

https://github.com/AndreiD/testingpushnotifications

SERVER_API_KEY と Client_Token を忘れずに置き換えてください。

PS。 私が書いた

于 2016-12-02T13:01:11.147 に答える