iOSでプッシュ通知を実装する方法の超詳細まとめ(後編)

APNS アイキャッチ

前編に引き続きiOSでのプッシュ通知の実装方法を詳細にまとめてみます。

後編ではルート証明書の準備~プッシュ通知の実装を行います。

ルート証明書の準備

プロバイダとAPNS間の通信に必要なルート証明書を取得します。

取得方法はapns-phpのWikiに記載されている内容を元にしています。
https://code.google.com/p/apns-php/wiki/CertificateCreation

ブラウザでEntrust.netのルート証明書ダウンロードページを開きます。
https://www.entrust.net/downloads/root_index.cfm

「Personal Use and Secure Server Installation」を選択し、「Download Certificates」ボタンを押下します。
Entrust.net パーソナルを選択
「Root Certificates」のリンクを選択します。
Root Certificate
「entrust_2048_ca.cer」を「リンク先のファイルをダウンロード」でダウンロードします。
※2010年12月22日までは、開発用には別の証明書もダウンロードする必要があったようですが、2013年8月21日現在では「entrust_2048_ca.cer」のみで開発用・製品用ともにAPNSとの通信が可能です。
Certification(2048)
ダウンロードしたファイルをダブルクリックするとキーチェーンに証明書が登録されます。

この証明書もpem形式に変換する必要があるため、キーチェーンアクセスで「”Entrust.net Certification Authority (2048)”を書き出す」を選択します。
PEM形式で書き出し
フォーマットはPEM形式(.pem)を選択し、「entrust_root_certification_authority.pem」というファイル名で保存します。
ルート証明書の保存

デバイストークンの取得

プッシュ通知を実装するアプリのコードで、デバイストークン取得のための処理を実装します。
デバイストークンを取得するためには、前編で作成したプロビジョニングプロファイルをアプリに組み込む必要があります。

ビルド用プロビジョニングプロファイルの設定

アプリのビルドに使用するプロビジョニングプロファイルは、開発用(Debug)と製品用(Release)でそれぞれ前編で作成したものを設定する必要があります。

プロビジョニングプロファイルはXcodeの「Build Settings」の「Code Signing」で設定します。
Code Signing

デバイストークン取得コードの実装

AppDelegate.mapplication didFinishLaunchingWithOptions:メソッド内で、registerForRemoteNotificationTypesメソッドを使用してリモート通知の登録を行います。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // バッジ、サウンド、アラートをリモート通知対象として登録する
    // (画面にはプッシュ通知許可して良いかの確認画面が出る)
    [application registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge|
                                                      UIRemoteNotificationTypeSound|
                                                      UIRemoteNotificationTypeAlert)];
    
    // Override point for customization after application launch.
    return YES;
}

プッシュ通知許可して良いかの画面でOKが押下された場合に呼び出されるデリゲートメソッドdidRegisterForRemoteNotificationsWithDeviceToken:を実装します。デバイストークンは<c4d30284 cd6b7dd0 43c3121b 7e49fad5 fb10f8c2 75dac94d a5d6ca87 d0f99fd3>のような形式で取得されますが、「<>」と半角スペースが不要なため、メソッド内で整形を行います。

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    // デバイストークンの両端の「<>」を取り除く
    NSString *deviceTokenString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    
    // デバイストークン中の半角スペースを除去する
    deviceTokenString = [deviceTokenString stringByReplacingOccurrencesOfString:@" " withString:@""];
    
    NSLog(@"%@",deviceTokenString);
}

処理後の文字列が、プッシュ通知で必要になるデバイストークンです。
文字列は後で必要になるので控えておきます。
デバイストークン

※今回はテストのためNSLogでデバイストークンを表示していますが、実運用では取得したデバイストークンをプロバイダに送信し、プロバイダ側のデータベース等に受け取ったデバイストークンを保持しておく等の方法が必要です。

プロバイダの準備

APNSと通信するためのプロバイダの仕組みを構築します。
APNSとの通信方法にはオープンソースのプログラム「apns-php」を使用します。

ダウンロードページより、apns-phpの最新版をダウンロードします。2013年8月21日現在の最新版はrevision 100です。
https://code.google.com/p/apns-php/downloads/list
apns-php ダウンロード一覧
apns-php revision 100
ダウンロードしたファイルを解凍すると下記のファイルが展開されます。
apns-php files
前編で作成した下記の証明書をsample_push.phpと同じ階層にコピーしておきます。

  • server_certificates_sandbox.pem (開発用の場合)
  • server_certificates_production.pem (製品用の場合)
  • entrust_root_certification_authority.pem

プッシュ通知の設定をするため、「sample_push.php」を編集します。

31行目付近

ApnsPHP_Pushのコンストラクタ第一引数、第二引数を編集します。

項目 概要
第一引数 開発用か、製品用かの環境変数を指定します。

開発用の場合「ApnsPHP_Abstract::ENVIRONMENT_SANDBOX」
製品用の場合「ApnsPHP_Abstract::ENVIRONMENT_PRODUCTION」

第二引数 プロバイダ証明書のパスを指定します。

開発用の場合「server_certificates_sandbox.pem」
製品用の場合「server_certificates_production.pem」

// Instanciate a new ApnsPHP_Push object
$push = new ApnsPHP_Push(
 ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
 'server_certificates_sandbox.pem'
);

37行目付近

前編で用意したルート証明書のパスを指定します。

// Set the Root Certificate Autority to verify the Apple remote peer
$push->setRootCertificationAuthority('entrust_root_certification_authority.pem');

44行目付近

「デバイストークンの取得」で取得したデバイストークンを指定します。

// Instantiate a new Message with a single recipient
$message = new ApnsPHP_Message('c4d30284cd6b7dd043c3121b7e49fad5fb10f8c275dac94dea5d6ca870f99fd3');

apns-phpのファイル一式とプロバイダ証明書ファイル、ルート証明書ファイルをPHPが動作するサーバーにアップロードします。

実機でのプッシュ通知確認

ブラウザでsample_push.phpにアクセスすると、デバイストークンで指定されたデバイスにプッシュ通知が送信されます。
プッシュ通知成功

ブラウザには下記のようなデバッグメッセージが表示されます。

Thu, 22 Aug 2013 00:27:57 +0900 ApnsPHP[25488]: INFO: Trying ssl://gateway.sandbox.push.apple.com:2195…
Thu, 22 Aug 2013 00:27:57 +0900 ApnsPHP[25488]: INFO: Connected to ssl://gateway.sandbox.push.apple.com:2195.
Thu, 22 Aug 2013 00:27:57 +0900 ApnsPHP[25488]: INFO: Sending messages queue, run #1: 1 message(s) left in queue.
Thu, 22 Aug 2013 00:27:57 +0900 ApnsPHP[25488]: STATUS: Sending message ID 1 [custom identifier: Message-Badge-000] (1/3): 167 bytes.
Thu, 22 Aug 2013 00:27:57 +0900 ApnsPHP[25488]: INFO: Disconnected.

うまくプッシュ通知できない場合

下記のものは開発用、製品用で内容が異なるため、環境によってすべて同じものを使用しているか確認してみてください。
私はこれでハマりました。

  • プロバイダ証明書
  • プロビジョニングプロファイル
  • デバイストークン
  • apns-phpの環境変数

おわりに

手順が長く複雑ですが、開発用・製品用を間違えないことを意識すれば二回目以降はそれほど苦労せずに実装可能だと思いました。最近ではAmazon SNSを利用したモバイルプッシュ通知も可能なようですが、仕組みを理解して使用するのも良い勉強になりました。