Apple Push Notification サービス(APNs) の実装方法

プッシュ通知の理解には、以下のドキュメントは、以下のものが参考になる
Local NotificationおよびPush Notificationプログラミングガイド

実装については、以下の公開されているコードが参考になる
・ApnsPHP: Apple Push Notification & Feedback Provider
http://code.google.com/p/apns-php/

・EASY APNS
APPLE PUSH NOTIFICATION SERVICE USING PHP & MYSQL
http://www.easyapns.com/
サーバ(PHP)、クライアント(Objective-C) のコードが同梱されている
また、HP には実装の手順が動画で公開されている(約10分)

今回 検証には、ApnsPHP を使用した。
(EASY APNS は mysqli を使用しているが、私の検証用レンタルサーバで動かなかったため。(T_T))

プッシュ通知を実装するには、以下の作業が必要となる

1. プッシュ通知に対応したプロビジョニングプロファイルの作成とインストール

– iOS Provisioning Portal から “Push Notifications”に対応した”App IDs”を取得する
– App IDs を指定したプロビジョニング ファイルを取得する
– 開発環境、デバイスにインストールする

プッシュ通知には、プッシュ通知に適応したプロビジョニング ファイルを使用する必要がある。
既に作成しているプロビジョニング ファイルにプッシュ通知 属性を付加することができなかったため、
新たにプッシュ通知に適応した “App IDs” を作成し、その ID を指定したプロビジョニング ファイルを取得した。

2. デバイストークンを取得する

デバイストークンとは、iOS デバイスが Remote Notification を受信するために、APNS へデバイス登録を行った際に取得できるID。
(サービス提供者が iOS デバイスへ APNS を介してメッセージ通知する際に利用される)

以下のサンプルでは、iOS アプリ起動時に Remote Notification 受信するためにデバイスを登録し、APNS からデバイス トークンを受信している。
(ログにデバイス トークンが出力されるので、PHPスクリプトに適用して利用する)

アプリ起動時などでデバイスを APNS へ登録する

1
2
3
4
5
6
7
// アプリケーションが起動した際の処理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Remote Notification を受信するためにデバイスを登録する
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge
                                                                           | UIRemoteNotificationTypeSound
                                                                           | UIRemoteNotificationTypeAlert)];

APNS から返されるデバイストークンに付加されている文字をカットする

1
2
3
4
5
6
7
// デバイストークンを受信した際の処理
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
 
    NSString *deviceToken = [[[[devToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""] 
                                                      stringByReplacingOccurrencesOfString:@">" withString:@""] 
                                                      stringByReplacingOccurrencesOfString: @" " withString: @""];
    NSLog(@"deviceToken: %@", deviceToken);

プッシュ通知は、NSDictionary で渡される

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// プッシュ通知を受信した際の処理
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
#if !TARGET_IPHONE_SIMULATOR
    NSLog(@"remote notification: %@",[userInfo description]);
    NSDictionary *apsInfo = [userInfo objectForKey:@"aps"];
 
    NSString *alert = [apsInfo objectForKey:@"alert"];
    NSLog(@"Received Push Alert: %@", alert);
 
    NSString *sound = [apsInfo objectForKey:@"sound"];
    NSLog(@"Received Push Sound: %@", sound);
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
 
    NSString *badge = [apsInfo objectForKey:@"badge"];
    NSLog(@"Received Push Badge: %@", badge);
    application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];
#endif
}

3. SSL Distribution証明書、秘密暗号鍵の取得とサーバへの配置

SSL Distribution証明書と秘密暗号鍵を、APNsに接続するサーバにインストールする必要がある。

私は以下の手順で証明書、秘密暗号鍵を作成しました。
ネット上にはいくつかの手順が紹介されていますが、以下の資料が一番わかりやすかったです。
結果、以下のファイルが作成できれば OK。

・server_certificates_bundle_sandbox.pem
・entrust_root_certification_authority.pem

How to generate a Push Notification certificate and download the Entrust Root Authority certificate

http://code.google.com/p/apns-php/wiki/CertificateCreation

・CertificateCreation
How to create a Push Notification certificate in iPhone Developer Program Portal

・Generate a Push Certificate
Push Notification のセキュリティ認証情報の取得

・Verify peer using Entrust Root Certification Authority
Download the Entrust Root Authority certificate directly from Entrust Inc. website:

4. PHPサーバ スクリプトの対応

最後に、iPhone へプッシュ通知するコードを用意します。
ApnsPHP の sample_push.php (プッシュ通知用)にデバイス トークンを指定すれば OKです。
また、APNS と通信するので、以下の証明書を配置しておきます。

– server_certificates_bundle_sandbox.pem
– entrust_root_certification_authority.pem

ここまで作業すれば、無事、プッシュ通知できるはずです。
お疲れ様でした。^_^

もし、PHP スクリプトがエラー出力するようであれば、以下の点をチェックしてみてください。
では!

注意:
ApnsPHP (at revision 100) – ApnsPHP-r100.zip に含められている sample_push.php は、
以下のファイル名の綴りが間違っているようです。
私はこれで2分くらい悩みました。。。(T_T)
2分で済んで助かりましたが、運が悪いともっと悩んでいたはず。
恐ろしい罠ですね。

1
2
3
4
5
6
// Instanciate a new ApnsPHP_Push object
$push = new ApnsPHP_Push(
	ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
//	'server_cerificates_bundle_sandbox.pem'		// 綴りが間違ってる
  'server_certificates_bundle_sandbox.pem'
);