Objective-Cでアプリにプッシュ通知の実装&はまりがちな罠

iPhoneアプリにプッシュ通知を送るための、アプリ側の実装の仕方について書きます。

デバイストークンの取得を要求する

iPhoneアプリにプッシュ通知を送るには、まず送信先のデバイスを識別するための、デバイストークンを取得する必要があります。

[[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];

プッシュ通知は、大きくわけて3種類、「テキスト」「サウンド」「バッジ」があります。「これは送らないよ」というものがあれば引数からはずしても構いません。

ユーザーへの確認後デバイストークンを受け取る

アプリのAppDelegateに、application:didRegisterForRemoteNotificationsWithDeviceToken:というメソッドを用意します。

- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    // デバイストークンが取得できる。
}

これは、UIApplicationDelegateに宣言されているメソッドで、Push通知のデバイストークン要求後、無事に取得ができた時に呼び出されます。

16進文字列に変換する

このデバイストークンを用いてプッシュ通知が送信できるので、これをサーバに送信します。デバイストークンは取得された時、NSDataでバイトデータですが、大抵のライブラリはこれを16進文字列で扱うので、ここで変換をかけてしまいます。

- (NSString *)stringWithDeviceToken:(NSData *)deviceToken {
    const char *data = [deviceToken bytes];
    NSMutableString *token = [NSMutableString string];
    for (int i = 0; i < [deviceToken length]; i++)
        [token appendFormat:@"%02.2hhX", data[i]];
    return [[token copy] autorelease];
}

How to use Objective C to send device token for push notifications and other user settings to sql table on server
出力後のトークンは次のような形になります。

hexToken: F89511E46FB822C905DFD99808E8589E2106B0EE3EE900EC6A6F5BA1B0F06527

これをHTTPなどを通してサーバに送信します。

シミュレータではデバイストークンの取得に失敗する

注意することは、iPhoneシミュレータで実行するときは、プッシュ通知のデバイストークンを取得することができないということです。UIApplicationDelegateには、デバイストークンの取得に失敗した時のためのメソッドが用意されています。

- (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"%@", error);
}

NSErrorが渡されるので、出力してみると次のようにシミュレータではPush通知ができないことがわかります。

Error Domain=NSCocoaErrorDomain Code=3010 "リモート通知はシミュレータではサポートされていません" UserInfo=0x8a1d1d0 {NSLocalizedDescription=リモート通知はシミュレータではサポートされていません}

シミュレータでは無理なので実機に転送してテストする必要がありますが、ただ実機に転送してもダメです。

アプリ設定でプッシュ通知を有効にする必要がある。

実機に転送してもエラーが出る場合があります。

Error Domain=NSCocoaErrorDomain Code=3000 "Appの有効な“aps-environment”エンタイトルメント文字列が見つかりません" UserInfo=0x1c578730 {NSLocalizedDescription=Appの有効\343\201\252“aps-environment”エンタイトルメント文字列が見つかりません}

これが出た場合、AppleのDeveloper Centerでアプリの設定を確認してください。
スクリーンショット 2013-08-13 20.11.21
App IDを作成したあとにPush Notificationsの設定を有効にしていないと、プッシュ通知のデバイストークンが取得できません。
ちなみに、プッシュ通知の実装をしていると時々apsという単語に出くわしますが、これはApple Push Notification Serviceの略だと思われます。APNSという言葉も良く登場します。

ワイルドカード証明書では失敗する

アプリを実機に転送するためには、ビルド設定のCode Signing Identityに、Provisioning Profileと呼ばれる証明書を設定する必要があります。
iOS Team Provisioning Profileというワイルドカード証明書を使うと、簡単に実機に転送できて良いのですが、この証明書はPush Notificationsの設定を有効にできないので、プッシュ通知のテストはできません。ワイルドカードではなく、アプリに一つのBundle Indentifierを設定して、App IDを作成してやる必要があります。
色々と壁があるので、結構大変です。無事にデバイストークンが取得できたら、次はサーバに実際にプッシュ通知を送信する機構を実装するステップに進みます。

これ使えば一発

そんなこんなでいくらか罠があって面倒なプッシュ通知ですが、GrowthPushのライブラリを使うと、アプリの実装は1行のソースコードを追加するだけで使えて、高速プッシュ通知配信ができるサーバまでついてきて無料なのでぜひ使ってください。
スクリーンショット 2013-08-13 20.18.51
GrowthPush
宣伝でした。

タイトルとURLをコピーしました