公式ドキュメント(日本語)
参考リンク
実装/準備
- http://iphone.longearth.net/2009/09/01/%E3%80%90iphone%E3%80%91push-notification%E3%81%AE%E5%AE%9F%E8%A3%85%E6%96%B9%E6%B3%95/
- 大いに参考にさせて頂きました
- http://onlineconsultant.jp/pukiwiki/?Push%E9%80%9A%E7%9F%A5%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B
- http://msdn.microsoft.com/ja-jp/windowsazure/hh852614.aspx
- iOSのRemote Notificationを試してみた - daicham blog
- http://developer.apple.com/library/ios/#technotes/tn2265/_index.html
- 公式のトラブルシューティング。APNsに接続確認する時にopenssl s_clientでやる方法をここで知りました
- Apple Push Notification Serviceを利用した、iPhone クライアントと、Rubyによるサーバの作成。 | cocoa*life
- プロバイダをRubyで作成されていたので参考に
- ちなみに今回プロバイダ側はRailsだったのでApns4r*1を使いました
その他
- Push Notification おさらい - その後のその後
- iOSアプリでプッシュ通知を完璧にテストする方法 - kenmazの日記
- Push通知についての選択を再度させるのはめんどうなんだなあ
iOS側
公式ドキュメントに書いてある手順は3つ。
1. アプリケーションがregisterForRemoteNotificationTypes:メソッドを呼び出します。
2. デリゲートはデバイストークンを受信するためにapplication:didRegisterForRemoteNotificationsWithDeviceToken:メソッドを実装します。
3. アプリケーションが、デバイストークンを非オブジェクトのバイナリ値としてプロバイダに渡します。
デバイスの認証
上記手順の1にあたります。APNsにデバイストークンを要求します。
要求する際にPush通知で使用する項目を指定する必要があります。
- UIRemoteNotificationTypeAlert
- Push通知に表示するメッセージ
- UIRemoteNotificationTypeBadge
- Push通知した際にアプリケーションのアイコンに件数を表示する(右上につく赤丸の数字)
- UIRemoteNotificationTypeSound
- Push通知した際にサウンドを鳴らす
デバイストークンを要求する際はregisterForRemoteNotificationTypesを実行します。
アプリ起動時に要求するようにするため今回はdidFinishLaunchingWithOptions内に記述しました。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //〜略〜 [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert)]; //〜略〜 }
上記はAlertのみ指定しています。複数している場合にはパイプで繋ぎます。
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound)];
デバイストークンの取得
上記手順の2にあたります。手順1が実行されデバイストークンの取得に成功するとコールバックでdidRegisterForRemoteNotificationsWithDeviceTokenがコールされます。
-(void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // 手順3 プロバイダにデバイストークンを送る処理等。HTTP通信などでプロバイダへ渡す }
引数のdeviceTokenの値が取得したデバイストークンになるためこの値をプロバイダに送信します
もしデバイストークンの取得に失敗した場合didRegisterForRemoteNotificationsWithErrorがコールされます。
プロバイダ側
今回プロバイダ側で使用したのはApns4rというRailsのプラグインを使用しました。
証明書と秘密鍵が必要になります。
必要な証明書と秘密鍵取得の手順は飛ばします。Macのキーチェーンアクセスに登録されている前提で進めます。
p12形式(PKCS#12形式)で証明書と秘密鍵を書き出します。(開発時の場合はこんな名前だと思われるApple Development IOS Push Services)
この際にハマったことがあって、書きだす際は必ずキーチェーンアクセスの分類で自分の証明書を選択して書き出します。
すべての項目にも該当証明書、秘密鍵は表示されていますが証明書をp12形式で書きだすことができません。
p12形式は証明書と秘密鍵がペアになった形式と理解しています。たしかに自分の証明書のところでみると証明書に秘密鍵が紐付いたような表示をしていますが、全ての項目の方では各々が独立しているようにみえます。
証明書をp12形式で書き出したらRubyで使う形式に変更する必要がある為下記コマンドを実行します。
## 証明書 openssl pkcs12 -clcerts -nokeys -out cert.pem -in 書きだした証明書.p12 ## 秘密鍵 openssl pkcs12 -nocerts -out key.pem -in 書きだした秘密鍵.p12 ## 秘密鍵のパスフレーズをなくす openssl rsa -in key.pem -out key-noenc.pem
この処理によって作成されたcert.pemとkey-noenc.pemを使っていきます。
Apns4rの設定方法などはREADMEなどをみればわかるので簡単に。
設定ファイルをconfig/apns4r.ymlに置いて、Rails.rootにcertディレクトリを作りenv毎に証明書と秘密鍵を置く。
ファイル名などはデフォルトの設定ファイルみて適当なファイル名にしときます
defaults: &defaults apns4r_cert_file: <%= Rails.root.join("cert", "apns_#{Rails.env}_identity.cer") %> apns4r_cert_key: <%= Rails.root.join("cert", "apns_#{Rails.env}_private_key.pem") %> apns4r_push_host: 'gateway.sandbox.push.apple.com' apns4r_push_port: 2195 apns4r_feedback_host: 'feedback.push.apple.com' apns4r_feedback_port: 2196
あとはデバイストークンを取得してREADMEに書いてあるPush通知の方法を試せばおk
n = APNs4r::Notification.create 'でばいすとーくん', { :aps => {:alert => "hoge"}} APNs4r::Sender.new.push n
とかやるとpush通知されます。
また、APNsはサンドボックス環境と製品環境でhostが異なり、また証明書、秘密鍵も異なります。
gateway.sandbox.push.apple.comこちらがサンドボックスのホストなので開発時はこちらを使う。(Apns4rはこのあたりをenvで判断して設定ファイルで切り替えてくれています)
証明書のBag AttributesのfriendlyNameにDeveloperと書いてあったらサンドボックス環境用でまだ実際に確認はしてないですがDistributionとあったら製品用だと思います。
Push通知受信時
iOS側の話に戻りますが、プロバイダからAPNsに送られた通知はデバイストークンに該当するデバイスに通知を送ります。
アプリがフォアグラウンドの時に通知をうけとるとdidReceiveRemoteNotificationが実行されます。
アプリがバックグラウンドの時はiOS側で通知を表示し、通知から起動を行うと起動時にパラメータ等を渡せるみたいです(まだやってみてない)
細部よくわかっていないため理解が進んだら都度修正とかしようと思います。