Android での端末グループ メッセージング

端末グループ メッセージングを使用すると、特定のグループに属する端末で動作しているアプリの複数のインスタンスに単一のメッセージを送信できます。通常、「グループ」とは、単一のユーザーに属する一連の異なる端末のことを指します。グループ内のすべての端末は、共通の通知キーを共有します。このキーは、グループ内のすべての端末にメッセージをファンアウトするために FCM で使用されるトークンです。

端末グループ メッセージングを使用するには、Admin SDK を使用するか、アプリサーバーに XMPP または HTTP プロトコルを実装します。1 つの通知キーで送信できるメンバーの最大数は 20 です。

端末グループの管理

端末グループにメッセージを送信する前に、次の手順を行う必要があります。

  1. グループに追加する端末それぞれについて、登録トークンを取得します。

  2. notification_key を作成します。これは、特定のグループ(通常はユーザー)とそのグループに関連付けられたすべての登録トークンをマッピングさせることで、端末グループを識別します。通知キーは、アプリサーバー上でも Android クライアント アプリ上でも作成できます。

端末グループの基本管理(グループの作成と削除、端末の追加や削除)は通常、アプリサーバーを介して行われます。サポートされているキーの一覧については、以前の HTTP プロトコルのリファレンスをご覧ください。

あるいは、Android クライアント アプリでクライアント側から端末グループを管理することもできます。

アプリサーバーでの端末グループの管理

端末グループの作成

端末グループを作成するには、グループの名前を指定する POST リクエストと、端末の登録トークンのリストを送信します。FCM は、端末グループを表す新しい notification_key を返します。

HTTP POST リクエスト

次のようなリクエストを https://android.googleapis.com/gcm/notification に送信します。

https://android.googleapis.com/gcm/notification
Content-Type:application/json
Authorization:key=API_KEY
project_id:SENDER_ID

{
   "operation": "create",
   "notification_key_name": "appUser-Chris",
   "registration_ids": ["4", "8", "15", "16", "23", "42"]
}

notification_key_name は、指定されたグループを一意に表す名前または識別子(たとえばユーザー名)です。notification_key_namenotification_key は、登録トークンのグループに対して一意になります。同じ送信者 ID のクライアント アプリが複数ある場合は、クライアント アプリごとに notification_key_name が一意であることが重要です。これにより、メッセージが目的のターゲット アプリだけに確実に送信されるようになります。

レスポンスの形式

リクエストが成功すると、次のような notification_key が返されます。

{
   "notification_key": "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ"
}

今後のオペレーションで使用するために、notification_key と、対応する notification_key_name を保存します。

端末グループでの端末の追加と削除

既存のグループで端末を追加または削除するには、operation パラメータを add または remove に設定した POST リクエストを送信し、追加や削除の対象となる登録トークンを指定します。

HTTP POST リクエスト

たとえば、登録 ID が 51 の端末を appUser-Chris に追加するには、次のリクエストを送信します。

{
   "operation": "add",
   "notification_key_name": "appUser-Chris",
   "notification_key": "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
   "registration_ids": ["51"]
}

レスポンスの形式

端末の追加または削除のリクエストが成功すると、次のような notification_key が返されます。

{
   "notification_key": "APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ"
}

Android クライアント アプリでの端末グループの管理

クライアント上で端末グループを管理できると、サーバーが利用できない場合に便利です。クライアント上で端末グループを作成するには、端末に少なくとも 1 つの Google アカウントがある必要があります。クライアント上で通知キーを作成するプロセスは、上記のサーバー側でのプロセスと大きく異なります。

クライアント上で端末グループを作成するには:

クライアント ID を取得する

  1. Google Developers Console でプロジェクトを開きます。
  2. 左上にある メニューから [APIs とサービス] を選択し、[認証情報] を選択します。
  3. [認証情報を作成] をクリックし、[OAuth クライアント ID] を選択します。
  4. [クライアント ID の作成] ダイアログで、アプリケーションの種類として [ウェブ アプリケーション] を選択し、[作成] をクリックします。
  5. クライアント ID に対して表示されている値をコピーします。このクライアント ID は idToken の生成に使用する Google アカウント「scope」を表します。

端末上で Google アカウントを検証する

Google Developers Console からクライアント ID を取得したら、端末に Google アカウントがあるかどうかを確認します。

// This snippet takes the simple approach of using the first returned Google account,
// but you can pick any Google account on the device.
public String getAccount() {
    Account[] accounts = AccountManager.get(getActivity()).
        getAccountsByType("com.google");
    if (accounts.length == 0) {
        return null;
    }
    return accounts[0].name;
}

認証トークンを取得する

次に GoogleAuthUtil クラスを使用して、認証トークン(idToken)を取得します。次に例を示します。

String accountName = getAccount();

// Initialize the scope using the client ID you got from the Console.
final String scope = "audience:server:client_id:"
        + "1262xxx48712-9qs6n32447mcj9dirtnkyrejt82saa52.apps.googleusercontent.com";
String idToken = null;
try {
    idToken = GoogleAuthUtil.getToken(context, accountName, scope);
} catch (Exception e) {
    log("exception while getting idToken: " + e);
}
...

グループに対して端末を追加または削除する

グループの登録トークンを追加または削除する、https://android.googleapis.com/gcm/googlenotification への HTTP POST リクエストを作成します。リクエスト ヘッダーでは project_id送信者 ID に、Content-Type が JSON に設定されている必要があります。

グループに追加する

追加オペレーションには、operation キー(add に設定)、id_token キー(上記の手順で取得した idToken に設定)、notification_key_name キー、registration_ids キーが必要です。userEmail 変数は、以下に示すように、accounts[0].name の値から派生できます。クライアントには、このメールまたはアカウントにマッピングされたグループだけを管理する権限が与えられています。

public String addNotificationKey(
        String senderId, String userEmail, String registrationId, String idToken)
        throws IOException, JSONException {
    URL url = new URL("https://android.googleapis.com/gcm/googlenotification");
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    con.setDoOutput(true);

    // HTTP request header
    con.setRequestProperty("project_id", senderId);
    con.setRequestProperty("Content-Type", "application/json");
    con.setRequestProperty("Accept", "application/json");
    con.setRequestMethod("POST");
    con.connect();

    // HTTP request
    JSONObject data = new JSONObject();
    data.put("operation", "add");
    data.put("notification_key_name", userEmail);
    data.put("registration_ids", new JSONArray(Arrays.asList(registrationId)));
    data.put("id_token", idToken);

    OutputStream os = con.getOutputStream();
    os.write(data.toString().getBytes("UTF-8"));
    os.close();

    // Read the response into a string
    InputStream is = con.getInputStream();
    String responseString = new Scanner(is, "UTF-8").useDelimiter("\\A").next();
    is.close();

    // Parse the JSON string and return the notification key
    JSONObject response = new JSONObject(responseString);
    return response.getString("notification_key");

}

追加オペレーションが成功すると、notification_key が返されます。今後のオペレーションで使用するために、この notification_key と、対応する notification_key_name を保存します。

グループから削除する

削除オペレーションには、operation キー(remove に設定)、id_token キー(上記の手順で取得した idToken に設定)、notification_key_name キー、registration_ids キーが必要です。

// HTTP request
JSONObject data = new JSONObject();
data.put("operation", "remove");
data.put("notification_key_name", userEmail);
data.put("registration_ids", new JSONArray(Arrays.asList(registrationId)));
data.put("id_token", idToken);

端末グループへのダウンストリーム メッセージの送信

端末グループへメッセージを送信する方法は、個々の端末へメッセージを送信する場合とよく似ています。この場合、to パラメータを端末グループの一意の通知キーに設定します。ペイロード サポートの詳細については、メッセージのタイプをご覧ください。このページの例では、HTTP プロトコルと XMPP プロトコルで端末グループにデータ メッセージを送信する方法を示しています。

端末グループの HTTP POST リクエスト

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to": "aUniqueKey",
  "data": {
    "hello": "This is a Firebase Cloud Messaging Device Group Message!",
   }
}

端末グループの HTTP レスポンス

以下は「成功」の例です。notification_key には 2 つの登録トークンが関連付けられており、メッセージは両方のトークンに正しく送信されました。

{
  "success": 2,
  "failure": 0
}

以下は「一部成功」の例です。notification_key には 3 つの登録トークンが関連付けられています。メッセージは、そのうち 1 つの登録トークンだけに正しく送信されました。レスポンス メッセージには、メッセージを受信できなかった登録トークンがリストされます。

{
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

notification_key に関連付けられた 1 つ以上の登録トークンにメッセージを配信できない場合、アプリサーバーはバックオフを行いながら再試行を繰り返します。

端末グループの XMPP メッセージ

  <message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to": "aUniqueKey",
      "message_id": "m-1366082849205" ,
      "data": {
          "hello":"This is a Firebase Cloud Messaging Device Group Message!"
      }
  }
  </gcm>
</message>

端末グループの XMPP レスポンス

グループ内のいずれか 1 つの端末にメッセージが正しく送信されると、XMPP 接続サーバーは ACK で応答します。グループ内のすべての端末に送信されたメッセージがすべて失敗した場合は、XMPP 接続サーバーは NACK で応答します。

以下は「成功」の例です。notification_key に 3 つの登録トークンが関連付けられており、メッセージはそれらすべてに正しく送信されました。

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success": 3,
  "failure": 0,
  "message_id": "m-1366082849205"
}

以下は「一部成功」の例です。notification_key には 3 つの登録トークンが関連付けられています。メッセージは、そのうち 1 つの登録トークンだけに正しく送信されました。レスポンス メッセージには、メッセージを受信できなかった登録トークンがリストされます。

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

FCM 接続サーバーがグループ内のすべての端末への配信に失敗すると、アプリサーバーは NACK レスポンスを受け取ります。

メッセージ オプションの全一覧については、選択した接続サーバー プロトコル(HTTP または XMPP)のリファレンス情報をご覧ください。

端末グループへのアップストリーム メッセージの送信

クライアント アプリは、to フィールドに適切な通知キーを設定してメッセージの宛先を指定することによって、端末グループにアップストリーム メッセージを送信できます。

FCM に次の呼び出しを行うことで、アップストリーム メッセージが通知キーに送信されます。オブジェクトは Key-Value ペアで構成されます。

FirebaseMessaging fm = FirebaseMessaging.getInstance();
String to = aUniqueKey; // the notification key
AtomicInteger msgId = new AtomicInteger();
fm.send(new RemoteMessage.Builder(to)
  .setMessageId(msgId)
  .addData("hello", "world")
  .build());

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。