以前書いたiOS7で可能になったAppのバックグラウンド更新を調べたという記事が好評のようなので、バックグラウンド更新との関係が深いPUSH通知について、調べてみました。
iOSのPUSH通知(APNs: Apple Push Notification service)というと、なかなか面倒な証明書絡みの設定と、デバイストークンのやりとりが必要で、その辺を説明した多くのブログ記事は、だいたいデバイストークンまで書いたら力尽きているのではないか・・・という気がします。
なので、その辺はすっぱり端折ってしまいまして、通知の種類というものにだけ、フォーカスしてみようと思います。
Remote NotificationとLocal Notification
まず、通知にはRemote NotificationとLocal Notificationがあります。
Remote Notificationは、外部のサーバから、Appleの提供するゲートウェイを介してiOS端末にPUSH通知を行うもので、皆さんの想像するいわゆる「PUSH通知」はこちらでしょう。iOS端末にPUSH通知が届くと、iOSの通知センターでアラートを出したりバッジを表示したりといった形で処理されます。
もう一つ、Local Notificationというものもあって、これはiOS端末内でアプリから通知センターに通知を出すもので、例えばローカルで動作するToDoアプリが決まった時間にアラートを出すようなケースで使用されます。
通知の種類
APNsにおける通知の種類は、ざっくり言えば下記4つの要素の組合せで構成されます。
- 通知センターへの通知の有無
- バッジやサウンドの有無
- カスタムペイロードの有無
- バックグラウンド更新の有無
APNsにおける通知は、下記のようなJSONメッセージです。
{
"aps":{
"alert": "New Message",
"badge": 3,
"sound": "sound1.aiff",
"content-available": 1
},
"name": "value"
}
ここで、apsの中に入っているのがAppleの決めた項目、apsの外にあるもの(この例では”name”:”value”)がカスタムペイロードといって、開発者が自由に使って良い領域です。
重要なのはapsの中の項目です。
alertを指定しておくと、PUSH通知が来た際、通知センターがアラートをバナーやダイアログの形で表示します。
alertを省略すると、バナーやダイアログは表示されません。これはサイレント通知と言われるようです。通知したいのにサイレントとはこれ如何に?と思うところですが、バッジだけを出したい場合とか、バックグラウンド更新だけを「こっそり」やっておきたい場合に使うことが出来ます。
badgeとsoundはそのままです。それぞれ値を指定すると、通知時にバッジ(アプリアイコンの右上に出る数字)を表示したり、サウンドが再生されたりします。
content-availableは、バックグラウンド更新において、極めて重要です。
iOS7で可能になったAppのバックグラウンド更新を調べたに書いたように、iOS7からはRemote Notificationをトリガーとしたバックグラウンドでのサーバ同期処理が書けるようになりました。
その際、UIApplication:didReceiveRemoteNotification:fetchCompletionHandlerというメソッドが呼び出されるのですが、バックグラウンド時に本当にこのメソッドが呼び出されるようにするためには、content-available:1という項目が通知に入っていなければなりません。(値は常に「1」でOK)
バックグラウンド時の通知とフォアグラウンド時の通知
PUSH通知が行われた際のアプリの状態によっても、通知の挙動は変わります。
アプリがバックグラウンド時に通知が行われた場合の挙動は、分かりやすいでしょう。通知で指定したとおりのアラート、バッジ、サウンド、バックグラウンド更新が行われます。
注意するべきは、上記のようにcontent-available=1を付けておかないと、UIApplication:didReceiveRemoteNotification:fetchCompletionHandlerが呼び出されない(=そこに記述されるであろう更新処理が動かない)ことです。
一方、アプリがフォアグラウンド時に通知が行われた場合、アラートは動作しません。
しかし、content-available=1の有無に関わらず、UIApplication:didReceiveRemoteNotification:fetchCompletionHandlerが呼び出されるので、その中の処理として、alertのメッセージを取得し、Local Notificationを作成して通知センターに通知したり、アプリ内で独自のダイアログを出すといったことを記述することが出来ます。
まとめ
色々書きましたが、言いたいことは2つ。
- バックグラウンド更新がやりたかったら、content-available=1は必須
- アプリのフォアグラウンド時の通知でアラートを出すには、何らかのコードが必要
以上です。