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 件のコメント:
コメントを投稿