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

In-App Billing v3 - 不检测退款

测试 Android In App Billing 真实购买

Android支付接入:Google In-app-Billing

Android支付接入之Google In-app-Billing