やらなイカ?

たぶん、iOS/Androidアプリの開発・テスト関係。

Google Cloud Messaging (GCM) の新機能 Topic Messagingを試したメモ

Google I/O 2015で発表された Google Cloud Messaging(以下GCM)の新機能、Topic Messagingを試してみました。

環境、前提条件などは、先の記事を参照してください。

nowsprinting.hatenablog.com

Topic Messaging とは

Topic Messagingとは、従来のGCMおよびApple Push Notification Service(以下APNs)のような送信先デバイスのトークンを指定してのPush通知ではなく、Publish/subscribeモデルのPush送信を行なう機能です。

Publish/subscribeモデルとは、各デバイスから購読(subscribe)したいトピックをあらかじめ登録することで、メッセージ送信(publish)側では個々のデバイスを意識することなく、トピックに対してメッセージを送ることで購読デバイスすべてにメッセージを配信できるものです。

これによって、例えば、

  • ニュースの更新などをPush通知したいだけであれば、サーバアプリケーションでは受信デバイスのRegistration Tokenを管理する必要がない
  • 送信機能もクライアントアプリに持たせる場合、サーバアプリケーション自体を立てる必要がない

といった構成が実現できるようになります。

制約・制限

GCMのTopic Messagingには、以下の制約・制限があります。

  • トピックのキーは、/topics/[a-zA-Z0-9-_.~%]+の書式
  • アプリあたり*1の購読数は100万件まで
  • トピックに送信できるメッセージのペイロードは2KBまで

購読数については、ユーザが1トピックづつ購読して100万ユーザまで、平均2トピックなら50万ユーザまで…となるので、インストール数が見込まれるアプリでは注意が必要です。

トピックの購読

以下、前回同様 Try Google Cloud Messaging for iOS のサンプルを使用して試していきます。

トピックの購読は、次のメソッドで行ないます。(メインスレッドから呼ぶ必要があります)

[GCMPubSub subscribeWithToken:topic:options:handler:]

サンプルのGcmExampleでは、起動時にトピック/topics/globalを購読するようになっています。

トピックへのメッセージの送信

続いて、同じく"Get started"のサンプルプロジェクトにあるGcmServerDemoを起動すると次のウィンドウが表示されます。

f:id:nowsprinting:20150607043716p:plain

apiKey欄にGCMのAPI Keyを入力し、"Send to topic"ボタンをクリックすると、送信メッセージの(本来、宛先のRegistrationTokenを設定する)toに、/topics/globalを設定して送信が行われます。

具体的には、以下のメッセージが送られます。

[
    "to": "/topics/global",
    "notification": [
        "body": "Hello from GCM"
    ]
]

これだけで、トピック/topics/globalを購読しているデバイスすべてにPush通知が送信されます。

トピックメッセージの受信

受信は通常のPush通知と同様です。受信側でトピックメッセージ固有の処理を行いたい場合は、 [UIApplicationDelegate application:didReceiveRemoteNotification:]メソッドで以下のように判定できます。

-(void)application:(UIApplication)application
        didReceiveRemoteNotification:(NSDictionary)notification {
    if ([notification[@"from"] hasPrefix:@"/topics/"]) {
        // トピックメッセージを受信した
    } else {
        // 通常のメッセージを受信した
    }
}

なお、今のところ、購読されているトピックのリストを取得するようなインタフェースは、サーバ側にもクライアント側にも定義されていないようです。

その他、エラーハンドリングなど詳細は公式のガイドを参照してください。

Implementing Topic Messaging

App nameとBundle ID, Androidアプリとの関連

GCMの利用登録を行なうページでは、"App name"と"iOS Bundle ID"を入力します。ここで、"App name"は、Google Developer Console(API Console)の"Project name"となります。

f:id:nowsprinting:20150615112845p:plain

これに対し、"iOS Bundle ID"は1:nの関係で登録することが可能です。 同様にAndroidアプリ場合、Bundle IDの代わりに"Android package name"欄にパッケージ名(ApplicationID)を登録しますが、これも1:nの関係になります。

トピックメッセージを送信するためのAPI Key、およびSender IDは、"App name"単位に割り当てられます。これに、複数の"iOS Bundle ID", "Android package name"を紐付けられますので、iOS版とAndroid版、また、Lite版やOEMしたアプリなどに対し、一括してトピックメッセージを送信することができます。

なお、iOSアプリ向け設定ファイルであるGoogleService-Info.plistにはSender IDしか書かれていませんので、複数のビルドターゲットで共有することができます。

Androidアプリ向けのgoogle-services.jsonには、Sender IDのほかに登録されたパッケージ名が書かれますが、登録されたパッケージ名が全て配列で書かれるようです。 そのため、フレーバーを定義して複数のアプリをビルドする場合でも、ひとつのgoogle-services.jsonを共有して問題ありませんでした。

*1:おそらく、Google APIs ConsoleのProject単位のこと