StoreKitのバックグラウンド時のトランザクションの挙動が少し変わった件

Twitterで@naokitsさんに教えていただいたので検証してみました。以前この記事に書いた通り、今まではトランザクションが進行中にアプリがバックグラウンドに移行してしまうと、トランザクションオブザーバーがトランザクションのアップデート通知を受け取れなくなってしまうという問題があったのですが、最近この挙動に変更があったようです。幸い手元にiOS 5.1.1, 5.0, 4.3.3の端末があったのでそれぞれで検証してみました。

元々の挙動

2012年1月時点で検証した内容は下記の用になっています。

…SKPaymentTransactionStatePurchasedが完了する前にアプリケーションを切り替えてバックグラウンドにしてみると、

16:08:42.131 purchasing.

ログはこの状態で止まり、バックグラウンド状態ではObserverはSKPaymentTransactionStatePurchasedの通知を受け取れません。

アプリケーションがバックグラウンドに入ってしまうと、トランザクション完了時のSKPaymentTransactionStatePurchasedの通知が受け取れず、トランザクションがどういう状態にあるのかアプリケーション側から把握できなくなってしまう問題がありました。
ちなみにこの問題はバックグラウンドに入るときに一度observerをリムーブしてフォアグラウンドに戻ったときに再度observeし始めることで、回避できました。

iOS 5.1.1で再検証

この部分の挙動が変わったということだったので、iOS 5.1.1で再検証してみました。
ObserverのpaymentQueue:updatedTransactions:が呼ばれたタイミングでログを出力するようにし、バックグラウンドに入った時もobserveし続けるようにプログラムを変更してから実際に購入を試みてみました。

11:45:21.060 StoreKitTest[7014:707] SKPaymentTransactionStatePurchasing: <SKPaymentTransaction: 0xc67df00>
// ここでバックグラウンドに移行
// しばらく待つ
// フォアグラウンドに戻す
11:45:30.212 StoreKitTest[7014:707] SKPaymentTransactionStatePurchased. regular_mushroom2
11:45:30.288 StoreKitTest[7014:707] Transaction removed. 1000000049329408

以前と違って、バックグラウンドの間に進行したトランザクションの通知を受け取れるようになっていました。

公式情報の更新

Appleの公式ドキュメント「In-App Purchase Programming Guide」と「StoreKit Framework Reference」を見てみると、それぞれ更新日時が2012-02-16、2011-07-26となっていますが、古いAPIにdeprecatedがついたくらいでトランザクションオブザーバーの挙動についての記述の変更はありません。

iOS 5.0 / 4.3.3でも同じ挙動に

OSのアップデートによってStoreKit側のプロセスの挙動が変わったのかなと思ったのですが、念のためiOS 5.0 / 4.3.3の端末でも検証してみたところ、こちらでもバックグラウンド時のトランザクション進行の通知を受け取れるようになっていました。さすがにStoreKitの通信のパケットを分析するのは色々問題がありそうなのでやめておきますが、どうやらサーバーとの通信部分でなんらかの変更が行われた可能性が高そうです。

結論

例によって公式な情報がない状態なので、この挙動をどこまで信用してよいのかわかりませんが、この挙動が新しい仕様だとすると今までのようにバックグラウンドに入るタイミングでobserveを停止/再開する必要がなくなるので若干実装が楽になります。バックグラウンド時にobserveを停止/再開する方法も、公式なドキュメント等で指南されている方法ではなく、割と無理矢理な方法であったので、デベロッパから見ると今回の新しい挙動はある意味自然で歓迎すべき仕様と言えそうです。
というわけで、毎度おなじみになってきましたが、
公式な資料での説明がほしい…。

Pocket

「StoreKitのバックグラウンド時のトランザクションの挙動が少し変わった件」への1件のフィードバック

コメントを残す

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