我是第一次实施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");
我第二次尝试购买该商品时,我的OnIabPurchaseFinishedListener
被调用,我在日志中看到purchase failed
:“应用内结算错误:无法购买商品,错误回复:7:物品已经拥有“
这是有道理的,但是如果我尝试购买另一个项目,那么我的应用程序崩溃并出现以下错误:
java.lang.IllegalStateException:无法启动异步操作 (launchPurchaseFlow)因为另一个异步 operation(launchPurchaseFlow)正在进行中。
当我尝试进行失败的购买时,onActivityResult
回调不会发生,因此失败的启动流程无法得到处理和清理。因此,当我尝试另一次购买时,这就是崩溃的原因,因为它仍然处于最后一次失败交易的中间。
我做错了什么?如何确保在失败后清除launchPurchaseFlow()?
答案 0 :(得分:43)
我认为您只需将更新的代码更新为应用内结算类,您就不应再遇到同样的问题了。
据我所知,谷歌尚未推出对SDK Manager的更改。只需将新类复制/粘贴到您的类中,您就不应再遇到问题了。
截至3月15日更改的类是:IABHelper.java,Inventory.java,SkuDetails.java和一些MainActivity.java文件
答案 1 :(得分:29)
我知道这是对这个问题的后期贡献,但我今天遇到了同样的问题,我在一个片段中调用了应用程序计费,所以我查看了" labHelper.java"我看到了一个直接的解决方案,我相信这个问题...... 我修改了方法" void flagStartAsync(String operation)"在labHelper.java中,如下所示
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);
}
我希望这能帮助那些人......
答案 2 :(得分:10)
对我来说,最好的解决方法是将代码更新为最近的代码(here),并执行this post建议的代码:
1)公开方法
flagEndAsync
。它在那里,只是不可见。2)让每个听众调用
iabHelper.flagEndAsync
以确保程序被标记为正确完成;似乎所有听众都需要它。3)使用
try/catch
进行环绕声调用,以捕捉可能发生的IllegalStateException
,并以此方式处理。
更新代码不够的原因是我发现了仍然发生此错误(或至少有一个)的特殊情况:
IabHelper
; 答案 3 :(得分:8)
我有同样的问题。
我按照下载了当前的IabHelper.java jmrmb80's solution,但这不起作用。 (似乎repo现在是deprecated,我们应该依赖Android SDK管理器提供的版本。)所以我跟着Khan's advice:
iabHelper.flagEndAsync()
iabHelper.launchPurchaseFlow(...)
这似乎是一个公然的黑客!并且它可能具有不良副作用。但是,它确实“有效”......
经过进一步调查,我不认为上述解决方法解决了我的问题。我认为real solution将覆盖UI线程中的onActivityResult
。
答案 4 :(得分:2)
不需要hacky解决方案。 请求购买流程的活动或片段应具有以下内容:
@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的示例项目,在我的项目上进行了尝试,但它确实有效。
答案 5 :(得分:0)
Error response: 7:Item Already Owned
表示您购买的物品但尚未消耗,而您又尝试再购买。
当我在我的应用内活动singleInstance
中设置AndroidManifest launchMode时发生这种情况。应用程序总是以您描述的错误结束。
要避免此行为,请将launchMode更改为符合您需要的任何其他值
android:launchMode="singleInstance"
- > android:launchMode="singleTask"
我没有尝试深入理解为什么singleInstance不起作用。如果有人知道请提供更多信息。
所以我的解决方案是更改launchMode并使用已拥有的项目。从那时起,IAP对我来说很好。