Android In App Billing:无法启动launchPurchaseFlow,因为launchPurchaseFlow 正在进行中
Posted
技术标签:
【中文标题】Android In App Billing:无法启动launchPurchaseFlow,因为launchPurchaseFlow 正在进行中【英文标题】:Android In App Billing: Can't start launchPurchaseFlow because launchPurchaseFlow is in progress 【发布时间】:2013-03-15 17:19:58 【问题描述】:我是第一次实施 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) 因为另一个异步 操作(launchPurchaseFlow)正在进行中。
当我尝试购买失败时,onActivityResult
回调不会发生,因此失败的启动流程不会得到处理和清理。所以,当我尝试另一次购买时,这就是它崩溃的原因,因为它应该仍在最后一次失败的交易中。
我做错了什么?如何确保在失败后清理launchPurchaseFlow()?
【问题讨论】:
【参考方案1】:我相信您只需获取应用内计费类的更新代码,就不会再遇到同样的问题了。
据我所知,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 文件
【讨论】:
做到了,谢谢。我很高兴知道这不是我,因为我确信我已经按照他们所说的那样实施了它。 :) 这在我自己的设备上对我有用,但我仍然通过我的数十个更新了应用程序的用户设备中的 bugsense 报告得到错误(因此他们使用的是带有固定类的编译)。 @Fran 如果您让他们卸载/重新安装应用程序或进入设置 | 也会发生同样的事情。申请并清除 Google Play 应用的缓存? Google 为何没有更新他们随 SDK 管理器提供的代码?感谢您发布此消息! 昨天好像有更新了。不确定修复了哪些错误:code.google.com/p/marketbilling/source/list【参考方案2】:我知道这对这个问题的贡献有点晚,但是我今天遇到了同样的问题,我在一个片段中调用了应用内计费,所以我查看了“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);
我希望这会对那里的一些人有所帮助......
【讨论】:
如果您使用片段,这就是解决方案!基本上,如果在您尝试开始新操作时同步仍在进行中,则新部分将调用“flagEndAsync()”。这解决了我长期以来一直遇到的应用程序在付款后崩溃的问题! 大家都知道,这是一个糟糕的解决方案,它破坏了 flagStartAsync 方法的全部要点。这是解决此问题的正确方法:***.com/a/20485213/354793【参考方案3】:对我来说,最好的解决方法是将代码更新到最近的代码 (here),然后执行 this post 的建议:
1) 公开方法
flagEndAsync
。它在那里,只是不可见。2) 让每个侦听器调用
iabHelper.flagEndAsync
以确保程序正确标记为完成;似乎所有听众都需要它。3) 用
try/catch
包围调用以捕获可能发生的IllegalStateException
,并以这种方式处理。
更新代码还不够的原因是我发现了这个错误仍然存在(或至少一个)的特殊情况:
断开互联网连接; 进入您的应用; 让它初始化IabHelper
;
连接到互联网;
连接设备后,尝试购买。
【讨论】:
"使用 try/catch 包围调用以捕获可能发生的 IllegalStateException,并以这种方式处理。"这么重要的事情。 ;) @DinhNhat 实际上,写了这么久,我不记得“那样处理”是什么意思了。【参考方案4】:我也有同样的问题。
第一次尝试:解决方法
我下载了当前的IabHelper.java,按照 jmrmb80's solution,但这没有用。 (看来repo现在是deprecated,我们应该依赖Android SDK manager提供的版本。)所以我关注了Khan's advice:
将 IabHelper.flagEndAsync() 定义为 public,并且 在iabHelper.launchPurchaseFlow(...)
之前添加iabHelper.flagEndAsync()
这似乎是一个公然的黑客攻击!它可能会产生不良副作用。但是,它确实“工作”...
这似乎是一个已知错误:#134 和 #189。
第二次尝试:修复
经过进一步调查,我认为上述解决方法没有解决我的问题。我认为real solution 是在UI 线程中覆盖onActivityResult
。
【讨论】:
【参考方案5】:不需要千篇一律的解决方案。 请求购买流程的 Activity 或 Fragment 应具有:
@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 的示例项目,在我的项目中尝试过,它可以工作。
【讨论】:
【参考方案6】:Error response: 7:Item Already Owned
表示您购买了商品,但尚未消费,您尝试再次购买。
当我在应用内活动中将 AndroidManifest 启动模式设置为 singleInstance
时,这发生在我身上。应用程序总是以您描述的错误结束。
为避免这种行为,请将您的 launchMode 更改为适合您需要的任何其他值
android:launchMode="singleInstance"
-> android:launchMode="singleTask"
我没有试图深入理解为什么 singleInstance 不起作用。如果有人知道,请提供更多信息。
所以我的解决方案是更改启动模式并使用已拥有的项目。从那时起,IAP 对我来说效果很好。
【讨论】:
以上是关于Android In App Billing:无法启动launchPurchaseFlow,因为launchPurchaseFlow 正在进行中的主要内容,如果未能解决你的问题,请参考以下文章
您请求的项目不可购买 - android in app billing
测试 Android In App Billing 真实购买