In App Billingを初めて実装し、静的SKU IDを使用して最初の購入をテストしています。
初めてうまくいきました。 mHelper.launchPurchaseFlow(...)
を呼び出して、テスト購入を完了しました。私のアクティビティはonActivityResult
コールバックを受け取り、mHelper.handleActivityResult(...)
で処理するようにしました。すべてが素晴らしかった。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Pass on the activity result to the helper for handling
log("onActivityResult");
if (!this.mHelper.handleActivityResult(requestCode, resultCode, data)) {
log("cleared the launch flow");
// not handled, so handle it ourselves (here's where you'd
// perform any handling of activity results not related to in-app
// billing...
super.onActivityResult(requestCode, resultCode, data);
}
}
ただし、次の部分をテストしたかったため、アプリを再起動し、同じSKU(静的purchased
SKU)を購入しようとしました。
mHelper.launchPurchaseFlow(rootActivity, "Android.test.purchased", 10002,
new IabHelper.OnIabPurchaseFinishedListener() {
@Override
public void onIabPurchaseFinished(IabResult result, Purchase purchaseInfo) {
if (result.isFailure()) {
log("purchased failed");
} else {
log("purchase succeeded");
}
}
}, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
2回目に商品を購入しようとすると、OnIabPurchaseFinishedListener
が呼び出され、purchase failed
ログ内:「アプリ内課金エラー:アイテムを購入できません、エラー応答:7:アイテムは既に所有しています」
それは理にかなっていますが、別のアイテムを購入しようとすると、アプリが次のエラーでクラッシュします。
Java.lang.IllegalStateException:別の非同期操作(launchPurchaseFlow)が進行中のため、非同期操作(launchPurchaseFlow)を開始できません。
onActivityResult
コールバックは、失敗した購入を行おうとすると発生しないため、失敗した起動フローは処理されず、クリーンアップされません。そのため、別の購入を試みると、最後に失敗したトランザクションの途中にあると思われるため、クラッシュします。
私は何を間違えていますか?失敗後にlaunchPurchaseFlow()がクリーンアップされるようにするにはどうすればよいですか?
アプリ内課金クラスの更新されたコードを取得する必要があるだけで、同じ問題に再び直面することはないはずです。
Googleは、私が知る限り、SDKマネージャーへの変更をまだプッシュしていません。新しいクラスを自分のクラスにコピーして貼り付けるだけで、問題が発生することはなくなります。
ここで新しいコードの変更をご覧ください: https://code.google.com/p/marketbilling/source/detail?r=7ec85a9b619fc5f85023bc8125e7e6b1ab4dd69f&path=/v3/src/com/example/Android/trivialdrivesample/MainActivity .Java
3月15日の時点で変更されたクラスは次のとおりです。IABHelper.Java、Inventory.Java、SkuDetails.Java、およびMainActivity.Javaファイルの一部
私はそれが質問に少し遅れて貢献していることを知っていますが、今日同じ問題に直面していて、フラグメント内のアプリ課金を呼び出していたので、「labHelper.Java」を見て、私が信じる直接的な解決策を見ました問題は... labHelper.Javaのメソッド「void flagStartAsync(String operation)」を次のように変更しました
void flagStartAsync(String operation) {
if (mAsyncInProgress) {
flagEndAsync();
}
if (mAsyncInProgress) throw new IllegalStateException("Can't start async operation (" +
operation + ") because another async operation(" + mAsyncOperation + ") is in progress.");
mAsyncOperation = operation;
mAsyncInProgress = true;
logDebug("Starting async operation: " + operation);
}
私はこれがそこに誰かを助けることを願っています...
私にとって最良の解決策は、コードを最新のものに更新することです( here )、そして何をするか- この投稿 提案:
1)メソッド
flagEndAsync
をパブリックにします。そこにあり、見えないだけです。2)すべてのリスナーが
iabHelper.flagEndAsync
を呼び出して、プロシージャが適切に終了とマークされていることを確認します。すべてのリスナーで必要なようです。3)呼び出しを
try/catch
で囲んで、発生する可能性のあるIllegalStateException
をキャッチし、そのように処理します。
コードの更新が十分ではなかった理由は、このバグがまだ発生する(または少なくとも1つの)特別なケースを見つけたからです。
IabHelper
を初期化しましょう。私は同じ問題を抱えています。
jmrmb80のソリューション に従って、現在の IabHelper.Java をダウンロードしましたが、うまくいきませんでした。 (レポジトリは現在 非推奨 であり、Android SDKマネージャー)が提供するバージョンに依存する必要があるようです。)私は カーンのアドバイス =:
iabHelper.flagEndAsync()
の前にiabHelper.launchPurchaseFlow(...)
を追加しますこれは露骨なハックのようです!そして、それは望ましくない副作用があるかもしれません。しかし、それは「働きます」...
これは既知のバグのようです: #134 および #189 。
さらに調査した結果、上記の回避策で問題が解決したとは思いません。 実際のソリューション は、UIスレッドでonActivityResult
をオーバーライドすることだと思います。
ハッキングソリューションは必要ありません。購入フローをリクエストしているアクティビティまたはフラグメントには次のものが必要です。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (billingHelper == null) return;
// Pass on the activity result to the helper for handling
if (!billingHelper.handleActivityResult(requestCode, resultCode, data)) {
// not handled, so handle it ourselves (here's where you'd
// perform any handling of activity results not related to in-app
// billing...
super.onActivityResult(requestCode, resultCode, data);
}
else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
これはGoogleのサンプルプロジェクトのもので、私のプロジェクトで試してみたところ、うまくいきました。
Error response: 7:Item Already Owned
は、アイテムを購入したがまだ消費していないため、もう一度購入しようとしたことを意味します。
これは、singleInstance
へのアプリ内アシビティでAndroidManifest launchModeを設定したときに起こりました。アプリは常にあなたが説明したエラーで終了しました。
この動作を回避するには、launchModeをニーズに合った他の値に変更しますAndroid:launchMode="singleInstance"
-> Android:launchMode="singleTask"
SingleInstanceが機能しない理由を深く理解しようとしませんでした。誰かが知っているなら、もっと情報を提供してください。
したがって、私の解決策は、launchModeを変更し、既に所有しているアイテムを消費することでした。その時以来、IAPは私にとってはうまく機能しています。