[iOS 7] Remote notificationの挙動について

こんにちは、KID.Aです。

iOS 7からは「Background fetch」モードと「Remote notification」モードの新しいマルチタスク機能が追加されました。

「Background fetch」モードは指定した間隔(厳密には端末依存の間隔になります)でバックグラウンドアプリに通知が来る機能です。SNSのタイムラインなどの最新情報をユーザに見せたい場合に使えると思います。

「Remote notification」モードは、APNsからのプッシュ通知を受け取るタイミングで、バックグラウンドアプリにも通知が来る機能です。主に、ニュースアプリやコンテンツアプリなど定期的に情報更新が必要なアプリに相性がよい機能で、APNsの通知したタイミングでバックグラウンド処理が行えるため、予め重たいデータをダウンロードすることによって、アプリを起動した際に直ぐに最新の情報がみることができるようになります。

既に、色々なサイトでも既に紹介されているネタですが、「Remote notification」モードについて、詳細な挙動を調べてみましたので、記事にしたいと思います。

 

実装方法

「Remote notification」モードの実装方法を紹介します。

  • プログラム側

まずは、Xcodeを起動して、プロジェクトを作成します。プロジェクト名は「RemoteStudy」にします。

スクリーンショット 2013-10-11 9.21.53

次に、CapabilitiesのBackground Modesを項目を開きます。
スクリーンショット 2013-10-11 9.22.26

Background ModesをONにします。

スクリーンショット 2013-10-11 9.22.38

ModesのRemote notificationをチェックします。
スクリーンショット 2013-10-11 9.22.51

AppDelegate.mに以下のコードを実装します。

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler {
    NSLog(@"receive remote notification");
}

アプリがバックグラウンドで動いている際に、APNsからプッシュ通知がきたら、上記のメソッドに通知がされます。

以上で完了です。結構、簡単に実装できますね。

  • サーバ側

APNsで以下のJSONデータを送ります。

{ "aps": { "content-available": 1, "alert": "content test", "badge": 0, "sound": "default" } }

このプッシュ通知を受けると、プログラム側で実装したapplication:didReceiveRemoteNotification:fetchCompletionHandler:が呼ばれます。

alertを指定しないとSilent Notificationになりますので、端末の通知センターに通知されないため、これでユーザに気付かれずにAPNsの通知からバックグラウンド処理を行えることができます。

{ "aps": { "content-available": 1} }

※今回の記事ではプログラム側のAPNsの実装は記載しません。本来であれば、プログラム側にAPNsへ登録、デバイストークン取得・登録などの処理を追加しなければAPNsは動きませんが、詳しく書くと1記事分くらいになるため、省略させて頂きます。

 

実証

「RemoteStudy」アプリをインストール、起動後、ホームキーでアプリを終了します。

screen1

マルチタスクには以下の図のような状態で「RemoteStudy」アプリが残っています。

screen2

APNsのプッシュ通知を送ります。今回はparseというサービスを利用しました。

スクリーンショット 2013-10-11 10.09.43

端末にプッシュ通知が届いた後に、コンソールを見てみます。コンソールは Window→Organizerでツールを起動します。

スクリーンショット 2013-10-11 10.05.04

上のDevicesを選んで、左側の接続しているデバイス一覧から、自分のiPhoneのConsoleを押下するとログがみれるようになります。

スクリーンショット 2013-10-11 10.08.39

おおぉー、「receive remote notification」のログが表示されているということは、バックグラウンド状態でAPNsの通知をアプリが受け取ることができました。

 

詳細な挙動

さて、ここからがこのブログの本番です(笑)。
アプリの状態(未起動時、再起動時など)によってどう動作するか、現在の状況を検証しました。

まずは、application:didReceiveRemoteNotification:fetchCompletionHandler:が受けた際の挙動を知りたいため、APIを見ました。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html

——————————————————————————————-
Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running, the system calls this method regardless of the state of your app. If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method.
——————————————————————————————-

詳細をみると、もしアプリがサスペンド状態か未起動状態システム起動だったら、システムがアプリ起動してくれて、バックグラウンド状態にした後にメソッドが呼ばれると記載しています。

suspendedやnot runningの状態は下記のドキュメントで記載がありましたので、参考までに。

https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW2

 

検証

APIをみるとバックグラウンドにいなくても通知が来るのかな?と思い、検証してみました。

「RemoteStudy」アプリをインストール、起動後、ホームキーでアプリを終了します。

screen1

マルチタスクには以下の図のような状態で「RemoteStudy」アプリが残っています。

screen2

「RemoteStudy」アプリを上にスライドして、マルチタスクからアプリを終了させます。

screen3

プッシュ通知を送ります。

スクリーンショット 2013-10-11 10.09.43

コンソールにログが来ているか確認します。

スクリーンショット 2013-10-11 12.11.17

あれ?「receive remote notification」のログが来ていない・・・

APIに記載してあることと挙動が違うようにみえます。

 

問合せ

色々調べましたが、よくわかりませんでしたので、アップルに問合せてみました。

回答は、ユーザがマルチタスクで消したアプリには通知されないようです。ユーザが明示的に消したアプリに通知が来ることは混乱を招くから通知させないというものでした。

なるほどー。マルチタスクからアプリを消すと、Remote notificationモードが発動しなくなるわけですね。

ん?そしたら、ドキュメントに書いてある「If your app is suspended or not running, the system wakes up or launches your app and puts it into the background running state before calling the method.」ってなんだと思い、追加で問合せてみました。

回答は、同じような質問が来ていてドキュメント整備を確認している状態のようです。

もしかしたらドキュメントが直るかもしれないですね。

他にも、マルチタスク上にアプリが残っていれば端末を再起動しても通知されると回答を頂きましたが、実際試したら通知がきませんでした。これだけまだ謎です。

– 追記 2014/02/28
「マルチタスク上にアプリが残っていれば端末を再起動しても通知されると回答」の部分ですが、当時はiPhone4sでしか試せなかったため他の端末で試せなかったのですが、iPhone5sで試したところ問題なく動きました。iPhone4s(7.0.4時点)の結果だと再起動したら通知がこなくなります。

 

現状の挙動

アップルが回答があったものの、現状の挙動がどうなっているか知りたかったので、マトリックスにまとめてみました。試したのはiPhone 4sのiOS 7になります。

OKはアプリのapplication:didReceiveRemoteNotification:fetchCompletionHandler:に通知が届いた、NGは通知が届かなかった結果となります。

SnapCrab_NoName_2013-10-11_12-58-38_No-00

– 追記 2014/02/28
iPhone5sだと、7.0でもiPhone4sと挙動が若干異なります。
以下は、iPhone5s iOS 7.0で試した結果になります。

SnapCrab_NoName_2014-02

マルチタスクで動くとアップルが謳っている割には、ユーザの起動が必要というなんとも微妙な感じでした。「Remote notification」モードはAPNsが通知されても絶対にアプリに通知されるわけではなため、気を付けて設計して下さい。

KID.A

KID.A の紹介

楽して生きることと一発逆転を夢見ている、ちゃきちゃきのAndroiderです。 いろいろアプリを出しているのですが、いつもリリース後にターゲットユーザ数を2桁見誤っていたことに気付くので、残念でなりません。下方修正で、ヒットがでません。おしいです。 明日から本気出します。 よろしくお願いします。
カテゴリー: iOS タグ: , , , , , , パーマリンク

[iOS 7] Remote notificationの挙動について への2件のフィードバック

  1. koogawa のコメント:

    こんにちは。とても参考になりました。
    今日iPhone 5+iOS 7.1試したところ、マルチタスクから終了させても通知が来るようになっていました。一度お試しいただけると嬉しいです。

  2. KID.A KID.A のコメント:

    こんにちは。コメントありがとうございます。とてもうれしいです。

    本日、7.1端末が手に入りましたので挙動を確認してみました。
    僕はiPhone5s+iOS7.1(11D167)で確認しましたが、マルチタスクからアプリを終了させると、通知が来なかったです。(マルチタスクでアプリ終了後、プッシュ通知でdidReceiveRemoteNotificationに届きませんでした)。
    koogawa さんと何か条件が違うのだろうか・・・・。

    iPhone5が手に入りましたら、そちらでも確認しようと思います。
    引き続き、わかったことがありましたらコメント、ブログを更新しようと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です