整理したものはTech sheetsにあるよ

2016年2月7日日曜日

[Android]IabHelperは中断に対応できていない!

みんな、こんにちはー!

Androidでアプリ内課金(In-app billing)を実装するとき、Android SDKのサンプルとしてついてくるIabHelperをそのまま使ってる人、たぶん、いるよね!

購入時はこんなコードを書いているんじゃないかな?



private IabHelper mHelper;

void buyMokeMoney() {
    mHelper.launchPurchaseFlow(this, "product_money", REQUEST_PURCHASE, new IabHelper.OnIabPurchaseFinishedListener() {
        @Override
        public void onIabPurchaseFinished(IabResult result, Purchase info) {
            if (result.isSuccess()) {
                // upload receipt JSON to app server.
                sendReceipt(info);
            }
        }
    });
}

「購入処理が終わったら、レシート情報をサーバーに送信する」という処理だね。メソッド1つで購入の手続きができるのは、便利だよね。

でも、このIabHelperのlaunchPurchaseFlow()には、1つ構造的な欠陥があるんだ。

アプリにこのような実装をいれて、次のようなクレームがきたことはないかな?

「購入したのに仮想通貨が増えていません!返金してください!」

コードを見る限り、購入手続きが終わったらonIabPurchaseFinished()が呼ばれて、購入処理が成功していればアップロード処理が行われるはずだよね。

「おそらく購入後の通信に失敗していると思うので、アプリを再度起動してください。」みたいな回答をしてたりするんじゃないかな?

でもよく考えてみよう。購入処理で通信できていて、アプリのサーバーとの通信が失敗するって、なかなかレアケースじゃない?みんながすごい勢いで購入処理をやって、アプリのサーバーが処理できないことはあるかもだけど、ちょっと考えにくいよね。

なぜサーバーとの通信が失敗(したように見える)するんだろう?原因はIabHelperのlaunchPurchaseFlow()を使っているからなんだ。

launchPurchaseFlow()では、引数のActivityを使って購入処理用のIntentを発行しているんだ。ということは、購入処理中に電話かかってきたりして、アプリが中断状態になることがあるよね。

IabHelperのインスタンスは、初期化の手続きとかがあるのでActivityのフィールドにいれるよね。

あれ、中断時にこのIabHelperのインスタンス、保存してる?
というか、誰も保存していないよね!IabHelper、Parcelable/Serializableではないから。

これが、時々購入後の処理が実行されない原因なんだ。IabHelperは、構造的に中断に対応できていないんだ。

どうすればいいの? という答えは、次回!

0 件のコメント:

コメントを投稿