36

我是第一次实施 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(静态purchasedSKU)。

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()?

4

6 回答 6

43

我相信您只需要获取应用内计费类的更新代码,您就不应该再次遇到同样的问题。

据我所知,谷歌尚未推出对 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 文件

于 2013-04-02T06:20:15.990 回答
29

我知道这是对这个问题的迟到贡献,但我今天遇到了同样的问题,我在一个片段中调用了应用程序计费,所以我查看了“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);
}

我希望这会帮助那里的人......

于 2014-10-08T02:12:22.830 回答
10

对我来说,最好的解决方法是将代码更新到最近的代码(这里),并按照这篇文章的建议进行操作:

1)flagEndAsync公开方法。它在那里,只是不可见。

2) 让每个侦听器调用iabHelper.flagEndAsync以确保程序被正确标记为完成;似乎所有听众都需要它。

3) 用 a 包围调用try/catch以捕获IllegalStateException可能发生的情况,并以这种方式处理。

更新代码还不够的原因是我发现了这个错误仍然存​​在(或至少一个)的特殊情况:

  • 断开互联网连接;
  • 输入您的应用程序;
  • 让它初始化IabHelper
  • 连接到互联网;
  • 连接设备后,尝试购买。
于 2013-11-30T12:34:00.163 回答
8

我也有同样的问题。

第一次尝试:解决方法

根据 jmrmb80 的解决方案,我下载了当前的IabHelper.java ,但这不起作用。(现在似乎不推荐使用repo ,我们应该依赖 Android SDK 管理器提供的版本。)所以我听从了Khan 的建议

  • 将 IabHelper.flagEndAsync() 定义为公共的,并且
  • iabHelper.flagEndAsync()之前添加iabHelper.launchPurchaseFlow(...)

这似乎是一个公然的黑客攻击!它可能会产生不良副作用。但是,它确实“工作”......

这似乎是一个已知的错误:#134#189

第二次尝试:修复

经过进一步调查,我认为上述解决方法没有解决我的问题。我认为真正的解决方案onActivityResult是在 UI 线程中覆盖。

于 2014-10-09T09:51:30.607 回答
2

无需骇人听闻的解决方案。请求购买流程的 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.");
    }
}

那来自谷歌的示例项目,在我的项目上尝试过,它可以工作。

于 2016-09-10T17:30:47.970 回答
0

Error response: 7:Item Already Owned表示您购买了商品,但尚未消费,您尝试再次购买。

当我在应用内活动中将 AndroidManifest launchMode 设置为singleInstance. 应用程序总是以您描述的错误结束。

为避免这种行为,请将您的 launchMode 更改为适合您需要的任何其他值 android:launchMode="singleInstance"->android:launchMode="singleTask"

我没有试图深入理解为什么 singleInstance 不起作用。如果有人知道,请提供更多信息。

所以我的解决方案是更改启动模式并使用已经拥有的项目。从那时起,IAP 对我来说效果很好。

于 2014-01-08T10:58:01.803 回答