マンガゲットで開発を担当している武上です。最近2歳の息子がいろいろお話ができるようになってきました。今までずっとママと呼ばれていたのですが(男親も女親もどっちもママ)、ついにパパとよばれるようになりました!しかも稀に「パパだいすき」とかいってくれます!生きててよかった!
ところで、iOS5が半年前にリリースされてからアプリの通知周りのユーザビリティが随分上がりました。そこで今回は、その裏側で動いている、iOSとAndoroidのプッシュ通知の実装方法の違いについてまとめてみたいと思います。
ユーザがアプリを起動していなくとも、アプリにリアルタイムに何らかの通知を送る仕組みのことです。 iOSの場合はAPNS、Androidの場合はC2DMという名前で用意されており、それなりに容易に使うことができます。 どちらも基本は事前にユーザの許可を取った上で、AppleないしGoogleのサーバに通知を送ると、経由されて、OSに転送され、画面ないしアプリにアクションさせることができるという流れになっています。
iOSの場合:Appleサーバと通信する際に証明書が必要になるので、事前に作成しておく必要があります。Provisioning Portalから通知したいアプリの証明書を作成して、これをもとにpem形式の証明書を作ります。非常にめんどうです。
Androidの場合:事前登録が必要です。簡単です。
iOSの場合: 端末から通知用トークンを取得する際に、ユーザにダイアログが表示されて、パーミッションを得ることができます。拒否された場合は、トークンが通知されません。ダイアログは一度しか表示されないので注意です。設定アプリから通知の可否を変更することができます。
Androidの場合: マニフェストファイルでパーミッション(C2DMメッセージの送受信、登録)を記載しておきます。ユーザにはダウンロード時に表示されます。そのため許諾しない場合は、インストールできません。設定アプリで通知を解除できないので、アプリケーション側で解除できるよう設定項目として実装する必要があります。
iOSの場合:registerForRemoteNotificationTypesをコールして許可を取得します。許可されれば、UIApplicationDelegateのdidFailToRegisterForRemoteNotificationsWithErrorにトークンが渡されます。トークンはOSを別デバイスに復元したり、OSの再インストールなどで変更されるので、毎起動時に取得する必要があります。取得したトークンはサーバに保存しておきます。
Androidの場合: com.google.android.c2dm.intent.REGISTERのIntentでRegistrationIDを取得します。IDはBroadcastReceiverで受け取ります。受け取ったIDはサーバに保存しておきます。
iOSの場合::決まった形式(トークン、バッジ数、メッセージ、サウンド可否など)の通知ペイロードを作成し、バイナリインターフェースでAppleサーバに送信します。事前作成した証明書を使ってSSL通信を行います。複数件同時に送信できることができます。接続と切断を短期間で繰り返すとDOS攻撃とみなされて、接続が遮断されるので、なるべくまとめて送る必要があります。ペイロードの上限が256byte(メッセージではなく、ペイロード全体)なので、ローカライズ済の定型文をアプリ内に置き、必要な情報のみを追加パラメータで送るなどして、なるべく文字数を短縮しないと通知センターに十分な情報を表示できません。ペイロード作成を自分で実装するのは少々面倒ですが、ApnsPHPなどライブラリが多数あるので、これらを使うことで簡単に実装できます。配信に失敗した端末を取得できるAPIがあり、これを使うことでアプリがアンインストールされた端末を消しこむことができます。
Androidの場合:1通ごと、HTTPでPOSTします。data.パラメータで送信したデータがアプリに直接渡されます。通知が多すぎる場合などは、data.collabpse_keyを使って、通知をまとめることもできます(ただし順番は保証されないので、最新のものにまとめられるとは限りません)。ライブラリは特にありませんが、仕様がシンプルなので必要ないでしょう。
iOSの場合:ホームアイコンのバッジ、アラート、通知センターへの表示はiOSが勝手にやってくれます。通知センターをタップしてアプリを開くと、AppDelegateのapplication:didFinishLaunchingWithOptionsのパラメータに通知ペイロードが含まれるので、これを確認して、ハンドリングできます。アプリがフォアグラウンドのときは、application:didReceiveRemoteNotificationがコールされます。
Androidの場合:BroadcastReceiverからdataの中身をそのまま受け取る事ができます。アプリが自分でNotification APIを叩いて通知を表示する必要があります。手間は非常に多くなるのですが、Notification APIの機能をいろいろ使うことができるので自由度は高いです。
iOSの場合: 送信総数に制限はありません。ペイロードの上限が256byteで、少しでもメッセージが長くなると簡単に超過するので注意が必要です。 iOS3.0以上をサポートしており、事実上全ての端末で利用できます。配信は保証されないので、送信されない場合もあるとのことです。
Androidの場合: 1日あたりの送信総数に上限がありますが、Googleに申請することで上限を上げてもらうことができます。dataの上限は1024byteで、十分でしょう。Android2.2以上に対応しており、まだまだ2.1以下のままのユーザも多いので注意が必要です。送信、また通知順は保証されません。
どちらも基本的には同じようなシステムですが、iOSの方が必要な実装量が少なくきめ細やかで、Androidの方が必要な実装量が多く自由度が高いという違いがあるような気がします。