Remote Push Notification ASPサービスを試す

iOSのリモートプッシュ通知はアプリを起動していなくても能動的にユーザーに対する情報が送れるため、サービスへの動線を確保する上で非常に有効です。アプリのバージョンアップの通知に利用するだけでもユーザー離れを防ぐことができます。
リモートプッシュ機能を実装するためには、通知送出のプロバイダ(サーバ)を用意する必要があります。
最低限必要となるプロバイダの機能は下記の3つ。

  1. ユーザーのiOSのデバイストークンを受け取り管理する
  2. 管理しているデバイストークンに対して通知したい情報を送出する
  3. APNS(Apple Push Notification Service)からフィードバックを受け取る

一応、apns-php等がNew BSD Licenseで公開されていたりするので自前で作らなくともよいのですが、アプリのバージョンアップ通知のためだけに設置するのもちょっと大げさな気がします。
http://code.google.com/p/apns-php/

Remote PushのASPサービスについて

プロバイダ機能と管理コンソール、WebAPIをセットで提供してくれるASPサービスが存在します。プラン次第では制限付きで無料で利用可能なところがあります。


今回、即日利用可能なParseとpushwooshを試してみました。

実際に試してみる

ADCでAPNsへのデバイス認証のための鍵の作成

プロバイダを利用する際には、自前で用意しようとASPサービスを利用しようとアプリと一意に紐付けされたAPNs用の鍵が必須になります。

キーチェーンアクセスで証明書要求用のファイルを作成
キーチェーンアクセスのメニューから「証明書アシスタント」→「認証局に証明書を要求」

要求ファイルをディスクに保存します。


Apple Developer CenterにてAppIDを作成、Push Notificationを有効にしてAPNsのSSL証明書を取得します。
尚、Push Notificationを利用するアプリは一意である必要があるため、AppIDに*は利用できません。




XcodeのデフォルトのBundle IdentifierはProductNameによって動的に変わってしまうのでトラブルを防ぐ目的で、Bundle Identifierをリテラルで記述しておいた方がよいと思います。

キーチェーンで作成した要求ファイルをアップロードし、SSL証明書をダウンロードします。



ダウンロードしたSSL証明書はキーチェーンで内容を確認できます。
キーチェーン上の名前は変更できるようです。後で書き出ししたりする可能性があるのでわかりやすいように変更しておくことをオススメします。(参考) http://d.hatena.ne.jp/SOMTD/20120130/1327937262


アプリを実機で動作させるためのプロビジョニングファイル作成を作成しておきます。




Parseを試す

ParseにログインしDashboardの「Create New App」よりAppを登録します。


ParseにAPNsのSSL証明書を渡す必要があるので、キーチェーンアクセスから登録済みの証明書(p12)ファイルを書き出しておきます。
この際パスワードは含めてはいけないようです。


Parse DashboardのSettingより「Push notifications」を選択し「Client push enabled」をONにし、先程作成した、p12ファイルをアップロードします。


Parse SDKの組込み

Parse SDKXcodeに組み込む必要があります。SDKはParse DashboardのDownloadsから取得できます。

ダウンロードしたSDKの中からParse.frameworkを対象のプロジェクトにドラッグ&ドロップします。更にいくつかのバイナリを追加する必要があります。プロジェクトのBuild PhasesのLink Binary With Librariesより下記のモジュールを追加します。

  • AudioToolbox.framework
  • Accounts.framework
  • AdSupport.framework
  • CFNetwork.framework
  • CoreGraphics.framework
  • CoreLocation.framework
  • libsqlite3.dylib
  • libz.1.1.3.dylib
  • MobileCoreServices.framework
  • QuartzCore.framework
  • Security.framework
  • Social.framework
  • StoreKit.framework
  • SystemConfiguration.framework
コーディング

AppDeletageで下記の実装を行います。

  • ParseのApplicationIDとClientKeyの設定する
  • iOSへRemoteNotificationTypeを登録する
  • APNsから受け取ったデバイストークンをParseへ登録する
  • Channelの登録
  • RemoteNotificationの受け取り処理

Header

#import <Parse/Parse.h>

AppDeletage#didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //Parseキー設定
    [Parse setApplicationId:@"xxxxxxxxxxxxxxxxxx"
                  clientKey:@"yyyyyyyyyyyyyyyyyyy"];

    //RemoteNotificationTypeを登録
    [application registerForRemoteNotificationTypes:
     UIRemoteNotificationTypeBadge |
     UIRemoteNotificationTypeAlert |
     UIRemoteNotificationTypeSound];

    return YES;
}

AppDeletage#didRegisterForRemoteNotificationsWithDeviceToken:

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken
{
    //デバイストークンをParseへ登録
    [PFPush storeDeviceToken:newDeviceToken];
    //Channelの登録
    [PFPush subscribeToChannelInBackground:@""];
}

AppDeletage#didReceiveRemoteNotification:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    [PFPush handlePush:userInfo];
}


Parse ApplicationIDとClientKeyはDashboardの各アプリのOverviewから確認できます。

ParseではPush通知をChannel毎にグルーピングして送出することが可能なようです。利用方法としてはアプリのバージョン、ユーザーの地域などが考えられます。Array構造になっているのでTagのような複合的グルーピングが可能だと思います。

動作させてみる

実機にインストールして起動します。するとDashboardのData Browzerにてデバイスの登録が確認できます。

push送信してみます。DashboardのPush Notificationsの「send push」から送信のデータを作成します。




一応、送出ログと通知が届いたデバイス数などの情報が確認できるようです。一応、スケジュール送信機能も存在していますが無料プランでは制限されているようです。



REST APIを利用して通知させてみましたが問題なく通知は行えました。

> curl -X POST \
  -H "X-Parse-Application-Id: xxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Parse-REST-API-Key: yyyyyyyyyyyyyyyyyyyyyyyy" \
  -H "Content-Type: application/json" \
  -d '{
        "channels": [
             ""
        ],
        "data": {
          "alert": "Push Test using REST API of Parse."
        }
      }' \
  https://api.parse.com/1/push


Push通知をメインアプリではない限り月100万回を超えるケースはほぼないと思います。REST APIも無料で使えるので後から自動化する際にもさほど苦なく移行できそうな気がします。SDKREST APIともに充実してるので細かい操作も行えそうです。



pushwooshを試す

APNs SSL証明書の取得までは同じ手順となります。Parseと同様、pushwooshにログインしてアプリケーションを登録します。
事前にAPNs SSL証明書の鍵を書き出しておきます。こちらはパスワードを含めても大丈夫です。

Certificate fileにはADCからダウンロードしたSSL証明書(.cer)、Key fileは先程書き出した鍵(.p12)をアップロードします。


次にMy Apps画面の右のペインからiOSSDKをダウンロードし展開します。
こちらはプロジェクト毎登録する方式となります。PushNotificationManager.xcodeprojを対象のプロジェクトにドラッグ&ドロップし、Build PhasesのTarget DependencesにPushNotificationManagerを追加し、Link Binary With LiblariesにCoreLocation.framework、libPushNotificationManager.aを追加します。

Build SettingでOther Linker Flagに「-ObjC」、Header Search Pathsにヘッダーのパスを指定します。


info.plistにPushwoosh_APPIDとApplicationCodeを設定します。ApplicationCodeはpushwooshのアプリ設定画面に記述してあります。


ソースの組込み

PushNotificationManagerはDelegateによりそれぞれ実装するようです。こちらはソースの組込みに若干癖があるので使い方はSampleを参考にした方がよさそうです。

Header

#import "PushNotificationManager.h"

AppDeletage

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	PushNotificationManager * pushManager = [PushNotificationManager pushManager];
	pushManager.delegate = self;
        return YES;
}

- (void) onPushAccepted:(PushNotificationManager *)manager withNotification:(NSDictionary *)pushNotification {
	NSString *pushExtraData = [manager getCustomPushData:pushNotification];
	if(pushExtraData) {
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Push Extra Data" message:pushExtraData delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
		[alert show];
		[alert release];
	}
}
@protocol PushNotificationDelegate

@optional
//succesfully registered for push notifications
- (void) onDidRegisterForRemoteNotificationsWithDeviceToken:(NSString *)token;

//failed to register for push notifications
- (void) onDidFailToRegisterForRemoteNotificationsWithError:(NSError *)error;

//handle push notification, display alert, if this method is implemented onPushAccepted will not be called, internal message boxes will not be displayed
- (void) onPushReceived:(PushNotificationManager *)pushManager withNotification:(NSDictionary *)pushNotification onStart:(BOOL)onStart;

//user pressed OK on the push notification
- (void) onPushAccepted:(PushNotificationManager *)pushManager withNotification:(NSDictionary *)pushNotification;

//user pressed OK on the push notification
- (void) onPushAccepted:(PushNotificationManager *)pushManager withNotification:(NSDictionary *)pushNotification onStart:(BOOL)onStart;
@end
動作させてみる

pushwooshのアプリ画面でメッセージを登録し「Woosh!」を押すと、Push送信されます。

カスタムされたPush送信も可能です。

こちらはスケジュール送信も無料プランで可能です。

感想

Parseとpushwooshは即日利用可能だったので試してみました。単純に管理コンソールからPush通知するだけならどちらも簡単で1日もかからずに実装が可能です。
バージョンアップ通知を行う程度のアプリ(月に1,2回程度)であれば、Parseの方が管理コンソールも使いやすくAPIも豊富でよさそうな気がします。スケジュール機能がなくともAPIを利用して簡単なスクリプトを組めば可能です。pushをウリとしているアプリであれば、push回数無制限のpushwooshの方がいいかもしれません。(そもそもpushがウリならパフォーマンス問題もあるので自前で構築すべきだとは思います)
CORE PUSHについては試していないので機会があったら試してみようと思いますが、実際の運用で使う場合5000デバイスの制限は厳しい気がします。
パフォーマンスについては不明ですが次回のアプリの運用にはParseを試してみようと思います。