やらなイカ?

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

Google Cloud Messaging (GCM) でiOSデバイスにPush通知を送る

Google I/O 2015で発表された、Google Cloud Messaging(以下GCM)を使ってiOSデバイスにPush通知を送る手順が公開されていたので試してみました。

developers.google.com

なお、GCMを使うと言っても最終的にiOSデバイスにPush通知を行うのは従来通りiOS標準のApple Push Notification Service(以下APNs)です。 従来、サーバアプリケーションが直接デバイストークンを管理し、APNsにメッセージを直接送信していましたが、サーバアプリケーション→GCM→APNsと、GCMを介してPush通知を行なうことができます。

GCMにおいて端末固有のトークンとなるRegistration Tokenは、iOSの(APNsの)Device Tokenとは異なる、次のような*1文字列です。

bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1pLTQ/8t-5QNiXbYwZYEWiSFD-frQKlsV8lgI

iOSアプリでGCMを利用するメリットとしては以下が挙げられます。すでにMBaaSのPush通知サービスなどを使っているのであれば、実現できているものだと思います。

  • iOSAndroidのデバイストークン(Registration Token)を一元管理できる
  • iOSAndroidのPush送信ロジックを共通化できる
  • Topic Messagingを利用することで、デバイストークン指定でなくトピック文字列指定で該当するデバイスにPush通知できる

環境

今回試した環境は以下の通りです。

  • OS X 10.10.3
  • Xcode 6.3.2
  • iOS 8.3(Push通知を受けるには実機である必要があります。シミュレータはNG)
  • GCMクライアントライブラリ 1.0.7

なお、GCMクライアントライブラリを利用するには、iOS 7以上が必要です。*2

事前準備

前述の通り、APNsを利用することになりますので、App IDごとの"Push Notification"を許可し、APNsのSSL証明書を生成しておく必要があります。

証明書は、Development(sand box)、Productionいずれも利用可能です。今回はDevelopmentのみ試しています。

サンプルアプリのビルド

以下、Try Google Cloud Messaging for iOSの手順について補足します。

  1. CocoaPodsでサンプルを取得します

    $ pod try Google

    使用するサンプルを聞かれるので、 4: Samples/gcm/GcmExample.xcodeprojを選択。Xcodeでサンプルプロジェクトが開きます。

    サンプルプロジェクトには、クライアント二種類(Objective-C版とSwift版)、送信側のMacアプリケーションの、計3つのビルドターゲットが含まれます。

  2. Google Developersサイトで、GCMのAppと、iOSアプリのBundle IDを登録します

    Try Google Cloud Messaging for iOSページにある"GET A CONFIGURATION FILE"ボタンで登録ページに遷移できます。

    ここでApp Name(Androidアプリと共有するならば同じ名前で)、アプリのBundle IDを入力し、続いてAPNsのSSL証明書(p12形式)をアップロードします。すると、API KeyとSender IDを取得でき、GoogleServices-Info.plistがダウンロードできます。

  3. GoogleServices-Info.plistをサンプルアプリ(クライアント側)に取り込みます

    GoogleServices-Info.plistには、Sender IDが書かれています。

  4. サンプルアプリ(クライアント)を実行します

    実行すると、GCMにRegistration Tokenが設定され、Push通知を受け取る準備が整います。また、Topic Messagingのためのトピック/topics/globalにも登録されます。

    なお、このときコンソールにRegistration Tokenが出力されていますので、文字列をコピーしておきます。

送信サンプルの実行

サンプルプロジェクトのGCMServerDemoが送信側のサンプルです。起動すると下図のウィンドウが表示されます。

f:id:nowsprinting:20150607043716p:plain

apiKey欄にGCMのAPI Key、Registration TokenにクライアントのRegistration Tokenを入力し、"Send notification"ボタンをクリックすると、該当するiOSデバイスにPush通知が届きます。

f:id:nowsprinting:20150607044650p:plain

送信フォーマット

GCMに渡すメッセージが、APNsの形式に置き換えられてデバイスに届きます。例えばサンプルでは以下のフォーマットをGCMに送っています。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM"
    ]
]

デバイス側ではPush通知のuserInfoとして、以下の形式で受け取ることができます。

aps =     {
    alert = "Hello from GCM";
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";

badge, sound

badgeとsoundも以下のように指定できました。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM",
        "badge": 10,
        "sound": "default"
    ]
]

iOSデバイスのアプリアイコンにバッジが付き、またPush通知の受信音が鳴ります。 またアプリでは下記形式で取得できました。

aps =     {
    alert = "Hello from GCM";
    badge = 10;
    sound = default;
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";

その他のパラメタ

上記以外のパラメタは、notification下、もしくはdata下に設定することでアプリに渡すことができます。

[
    "to": to,
    "notification": [
        "body": "Hello from GCM",
        "key2": "value2"
    ],
    "data": [
        "key1": "value1"
    ]
]

アプリでは下記形式で取得できました。

aps =     {
    alert = "Hello from GCM";
};
"gcm.message_id" = "0:1433613206212203%4deaf3f24deaf3f2";
"gcm.notification.key2" = value2;
key1 = value1;

notification下に書いたkey2は、受信側ではgcm.notification.key2というキーに置き換わっています。構造を見る限り、data下に置くほうがよさそうです。

ペイロードに指定できる内容の詳細はリファレンスを参照してください。

Notification payload support

Topic Messaging

Topic Messagingについては次の記事を参照してください。

nowsprinting.hatenablog.com

*1:GCMのサイト内にサンプルとして掲載されていたもので、実在のトークンではありません

*2:ただし、サンプルアプリをそのままiOS 7で動作させるとクラッシュします。iOS 8で導入された[UIApplication registerUserNotificationSettings]を呼んでいるためで、iOS 7以前では[registerForRemoteNotificationTypes]を使用するように書き換える必要があります