6

根据 Google 的教程,我使用 Play Billing Library 1.0 实现了应用内购买。我只有一件要购买的物品,当它被解锁时,我会显示一条长度为 Toast.LENGTH_SHORT 的 Toast 消息。但是,Toast 会在那里停留大约 10 秒,所以我假设它会被多次调用。当我通过 queryPurchases 解锁它时不会发生这种情况(如果有人早些时候购买了它并在此期间重新安装了应用程序)。

任何人都知道为什么 Toast 会停留这么久/为什么会被多次调用?

在我的 BillingManager 类中:

@Override
public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
    if (responseCode == BillingClient.BillingResponse.OK) {
        for (Purchase purchase : purchases) {
            handlePurchases(purchase);
        }
        mBillingUpdatesListener.onPurchasesUpdated(mPurchases);
    } else if (responseCode == BillingClient.BillingResponse.USER_CANCELED) {

    } else {

    }
}

public void handlePurchases(Purchase purchase) {
    //here could be validation on own server

    mPurchases.add(purchase);
}

Main Activity 实现 BillingUpdatesListener:

@Override
public void onPurchasesUpdated(List<Purchase> purchases) {
    for (Purchase purchase : purchases) {
        switch (purchase.getSku()) {
            case "premium":
                unlockPremium();
                break;
        }
    }
}

public void unlockPremium() {
    mPremiumUnlocked = true;
    savePremiumUnlocked();
    Toast.makeText(this, getResources().getString(R.string.premium_congrats), Toast.LENGTH_SHORT).show();
    mAdView.setVisibility(GONE);
}
4

5 回答 5

6

如果我理解正确,您说当您第一次购买应用内产品时,您会获得多个 Toast?

在 Billing 库的当前版本 (1.0) 中,发生这种情况是因为系统正在进行多个广播。

例如,如果您在库onPurchaseFinishedReceiver中的第 120 行查看或断点BillingClientImpl.java,则在购买后至少会调用两次。两次都附有应用内购买数据,但我注意到Action每次广播的意图都不同。

在第一次广播中,Action 是,com.android.vending.billing.PURCHASES_UPDATED但在第二次广播中是proxy_activity_response_intent_action。该库不会过滤掉 Action 值,因此所有这些广播都会导致您purchasesUpdatedListener被调用。

我没有进一步调查,但我认为我们可以从中得到的是发生了某种变化,并且认为有必要传播这种变化。

为避免多次吐司,除非您的高级功能已解锁,否则不要显示吐司。即如果它已经解锁,只需忽略更改通知。

顺便说一句,在 Android Studio 中调试购买流程是完全可以的。只需使用您的发布密钥签署您的调试 apk,并确保 apk 版本不高于 Play 商店中的版本。

buildTypes {

    debug {
        minifyEnabled false
        debuggable true
        signingConfig signingConfigs.release
    }


    release {
        minifyEnabled false
        signingConfig signingConfigs.release
    }
}
于 2017-09-21T14:36:05.177 回答
2

如果您的订阅活动在同一个应用程序进程中多次关闭并重新打开,那么如果以某种方式保持连接到 billingClient 的先前实例并且先前的连接仍然存在,则onPurchasesUpdated可能会被多次调用。PurchasesUpdatedListener我注意到我关闭和重新打开订阅活动的次数,onPurchasesUpdated在成功后被调用相同的数量launchBillingFlow

为了解决这个问题,我需要在活动破坏时结束连接,就像这样 -

@Override
protected void onDestroy() {
    super.onDestroy();
    if (billingClient!= null) {
        billingClient.endConnection();
    }
}
于 2022-02-12T08:35:37.030 回答
2

我不知道这是否适用于您的确切情况,但我们正在经历同样的事情,这是谷歌的一个错误。

有关详细信息,请参阅https://issuetracker.google.com/issues/66054158

编辑:我刚刚看到@goRGon 发布了同样的内容:)

西班牙多人的例子与上面描述的情况不同。在西班牙场景中,用户实际上购买了两份 IAP,因此它们是两张单独的收据,用户应该得到两份他们购买的任何东西的奖励。在错误场景中,一张收据会两次呈现给用户,因此实际上可以捕获重复的收据。但无论哪种方式,后端验证系统都需要适应代码中的黑客/错误,这些错误可能导致同一收据连续发送两次。

于 2017-09-22T22:48:17.477 回答
1

@Kuffs 的好答案和深入研究!

谷歌将很快修复多个电话:https ://issuetracker.google.com/issues/66054158

但是,即使 onPurchasesUpdate 被多次触发,您与计费流程的集成也应该有效,因为它无论如何都可能发生。例如,如果有人在具有相同@gmail 帐户的另一台设备上并行购买。一些国家(例如西班牙)的人们确实经常与许多朋友和家人分享他们的@gmail 帐户。

请检查TrivialDrive_v2实现以了解如何优雅地处理此类情况。

于 2017-09-22T22:29:34.023 回答
0

我希望它会帮助你

        _purchaseUpdatedSubscription =
        FlutterInappPurchase.purchaseUpdated.listen((productItem) {
      print('purchase-updated: ${productItem}');
      getDetails(productItem);
    });

        String orderId = '';
      getDetails(PurchasedItem purchasedItem) {
        if (purchasedItem != null) {
          if (orderId != purchasedItem.orderId) {
            orderId = purchasedItem.orderId;
            print('productItem.transactionReceipt : ${purchasedItem.transactionReceipt}');
            var decodedData = jsonDecode(purchasedItem.transactionReceipt);
            print('purchaseState : ${decodedData['purchaseTime']}');
    
            if (decodedData['purchaseState'] == 0) {
    
              if(purchasedItem.productId == selected_package) {
                print("Purchased successfully");
                onPurchased(purchasedItem);
              }
            } else {
              ShowMsg('Transaction Failed !, Something went wrong.');
            }
          }
        }
      }
于 2021-11-18T10:17:26.777 回答