java - 您如何检查用户是否在打开应用程序时购买了应用程序内购买?

标签 java android in-app-purchase in-app-billing

注意:我说的是从应用程序中删除广告的一次性购买。
谷歌说你应该调用BillingClient.queryPurchases()在您的 onResume()onCreate()但我不知道该怎么做。
首先,这是实际应用内购买的代码,
我刚从 youtube 教程中得到它,我什至不知道它是否完整:

private void setupBillingClient(Context c) { //connect to google play
    billingClient = BillingClient.newBuilder(c)
            .enablePendingPurchases()
            .setListener(this)
            .build();
    billingClient.startConnection(new BillingClientStateListener() {
        @Override
        public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                //The BillingClient is setup successfully
                loadAllSkus();
            }
        }

        @Override
        public void onBillingServiceDisconnected() {
            //TODO: implement retry logic to handle lost connections to Google Play by calling startConnection() again
        }
    });
}

private void loadAllSkus() {
    if (billingClient.isReady()) { //first check if BillingClient is ready
        final SkuDetailsParams params = SkuDetailsParams.newBuilder()
                .setSkusList(skuList)
                .setType(BillingClient.SkuType.INAPP)
                .build();

        billingClient.querySkuDetailsAsync(params, new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(@NonNull final BillingResult billingResult, @Nullable List<SkuDetails> skuDetailsList) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    assert skuDetailsList != null;
                    for (Object skuDetailsObject : skuDetailsList) {
                        final SkuDetails skuDetails = (SkuDetails) skuDetailsObject;
                        if (skuDetails.getSku().equals(sku)) { //if it found the sku in play store you can start billing flow
                            Purchase.PurchasesResult result = billingClient.queryPurchases(BillingClient.SkuType.INAPP); //use play store cache, no network
                            List<Purchase> purchases = result.getPurchasesList();
                            boolean isOwned = false;
                            if (purchases != null) //first check if he has already purchased
                                for (Purchase purchase : purchases) {
                                    String thisSKU = purchase.getSku();
                                    if (thisSKU.equals(sku)) {
                                        isOwned = true;
                                        Toast.makeText(getContext(), "You are a premium user", Toast.LENGTH_LONG).show();//TODO: Delete this toast
                                        //TODO: Remove purchase options and ads here
                                        break;
                                    }
                                }

                            if (!isOwned) {
                                buyButton.setEnabled(true);
                                buyButton.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        BillingFlowParams billingFlowParams = BillingFlowParams
                                                .newBuilder()
                                                .setSkuDetails(skuDetails)
                                                .build();

                                        if (getActivity() != null)
                                            billingClient.launchBillingFlow(getActivity(), billingFlowParams);
                                        dismiss();
                                    }
                                });
                            }
                        }
                        /* else if (skuDetails.getSku().equals("something else")) { //add other products

                        }*/
                    }
                }
            }
        });
    } else Toast.makeText(getContext(), R.string.billing_not_ready, Toast.LENGTH_LONG).show();
}

@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<com.android.billingclient.api.Purchase> purchases) {
    int responseCode = billingResult.getResponseCode();

    if (responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
        for (Purchase purchase : purchases) {
            handlePurchase(purchase); //acknowledge the purchase
        }
    } else if (responseCode == BillingClient.BillingResponseCode.ITEM_ALREADY_OWNED) {
        //already owned
    } else if (responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {

    }
}

private void handlePurchase(Purchase purchase) {
    if (purchase.getSku().equals(sku) && purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                    AcknowledgePurchaseParams.newBuilder()
                            .setPurchaseToken(purchase.getPurchaseToken())
                            .build();
            billingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {
                @Override
                public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                        Toast.makeText(getContext(), "Purchase Acknowledged", Toast.LENGTH_LONG).show();//TODO: Delete this maybe?
                    }
                }
            });
        }
        Toast.makeText(getContext(), R.string.purchase_done, Toast.LENGTH_LONG).show();
    }
}
所以显然要调用BillingClient.queryPurchases()我必须在每个 Activity 中重写所有上述代码?

最佳答案

方法BillingClient.queryPurchases()如您所知,返回所有当前拥有的购买项目的列表。
一次又一次地复制相同的代码总是一种不正确的方法/设计。
你需要做的是封装你的代码,让它尽可能独立于任何Activity或任何其他组件,这样它就可以被重用。
如需更好的方法,请查看 Google 的官方账单样本。您将看到所有计费逻辑都被封装,因此可以轻松重用。
java :https://github.com/android/play-billing-samples/tree/main/ClassyTaxiJava
Kotlin :https://github.com/android/play-billing-samples/tree/main/ClassyTaxiAppKotlin
一些澄清,如果您发现 sample 是关于订阅的并且您需要非消耗品,反之亦然。两者的计费库是相同的,不同的只是要查询的数据,例如订阅使用 BillingClient.SkuType.SUBS 对于非消耗品 BillingClient.SkuType.INAPP .但其余的,如何连接计费、如何确认、启动购买流程等,两者都是完全一样的。没有单独的 API 或不同的方式来实现它,您使用相同的 API 和相同的实现只是更改正在查询的内容。

关于java - 您如何检查用户是否在打开应用程序时购买了应用程序内购买?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64192846/

相关文章:

java - JPQL : Access inherited Attributes in a Query

java - 如何以编程方式检测项目何时在 RecyclerView 中可见?

java - 如何在 Selenium Webdriver 中使用异常处理?

Java String 类实习

java - 为单个 Spring Controller 指定消息转换器

java - Android Studio 更新到 3.4 后,工具菜单中不显示 SDK Manager 和 AVDManager

android - 使用 ListFragment 和 CursorLoader 时得到 "ListFragment cannot cast to"消息

iphone - 上线前测试应用内购买

android - 响应代码项目已购买但购买列表为空

c# - Windows Phone 应用内购买错误