使用“播放结算库”

时间:2018-04-18 11:46:29

标签: android

在我的应用中,我有订阅。我使用IInAppBillingService以经典方式实现了购买流程并检查订阅状态。我用这种方式遇到了一些问题。大约1%的用户抱怨说,在成功购买订阅后,这些订阅在应用程序中无效。我问Google Pla对这个问题的支持。他们建议使用新的播放结算库。我查看了说明https://codelabs.developers.google.com/codelabs/play-billing-codelab/#6中的示例。但是,此示例不考虑检查订阅的状态。

我还在页面https://developer.android.com/google/play/billing/billing_library.html上找到了以下内容:" Google Play服务会返回登录到设备的用户帐户所做的购买。如果请求成功,则播放计费库将查询结果存储在“购买对象列表”中。要检索列表,请调用PurchasesResult对象上的getPurchasesList()方法。"

所以从教程中的BillingManager类我添加了一个代码来检查订阅的购买:

public Purchase.PurchasesResult querySubscriptionPurchases() {
        return mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
    }

在MainActivity中使用BillingManager:

mBillingManager = new BillingManager(this);
        Purchase.PurchasesResult purchasesResult = mBillingManager.querySubscriptionPurchases();
        if (purchasesResult != null) {
            List<Purchase> p = purchasesResult.getPurchasesList();
        }

当我运行app时,在logcat中我看到&#34; I / BillingManager:onBillingSetupFinished()响应:0&#34;。连接成功了吗?

但purchaseResult为空,我无法获取购买列表以探索此列表包含的内容以获取有效订阅的SKU。在调试模式下,使用IInAppBillingService的经典方式成功返回购买,我有一个有效的订阅测试,它可以工作。

BillingManager的完整列表:

public class BillingManager implements PurchasesUpdatedListener {
    private static final String TAG = "BillingManager";

    private final BillingClient mBillingClient;
    private final Activity mActivity;

    private static final HashMap<String, List<String>> SKUS;
    static
    {
        SKUS = new HashMap<>();
        SKUS.put(BillingClient.SkuType.SUBS, Arrays.asList("no_ads", "sub2", "sub3"));
    }

    public BillingManager(Activity activity) {
        mActivity = activity;
        mBillingClient = BillingClient.newBuilder(mActivity).setListener(this).build();
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponse) {
                if (billingResponse == BillingClient.BillingResponse.OK) {
                    Log.i(TAG, "onBillingSetupFinished() response: " + billingResponse);
                } else {
                    Log.w(TAG, "onBillingSetupFinished() error code: " + billingResponse);
                }
            }
            @Override
            public void onBillingServiceDisconnected() {
                Log.w(TAG, "onBillingServiceDisconnected()");
            }
        });
    }

    @Override
    public void onPurchasesUpdated(@BillingClient.BillingResponse int responseCode,
                                   List<Purchase> purchases) {
        Log.d(TAG, "onPurchasesUpdated() response: " + responseCode);
    }

    public List<String> getSkus(@BillingClient.SkuType String type) {
        return SKUS.get(type);
    }

    private void startServiceConnectionIfNeeded(final Runnable executeOnSuccess) {
        if (mBillingClient.isReady()) {
            if (executeOnSuccess != null) {
                executeOnSuccess.run();
            }
        } else {
            mBillingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(@BillingClient.BillingResponse int billingResponse) {
                    if (billingResponse == BillingClient.BillingResponse.OK) {
                        Log.i(TAG, "onBillingSetupFinished() response: " + billingResponse);
                        if (executeOnSuccess != null) {
                            executeOnSuccess.run();
                        }
                    } else {
                        Log.w(TAG, "onBillingSetupFinished() error code: " + billingResponse);
                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                    Log.w(TAG, "onBillingServiceDisconnected()");
                }
            });
        }
    }

    public Purchase.PurchasesResult querySubscriptionPurchases() {
        return mBillingClient.queryPurchases(BillingClient.SkuType.SUBS);
    }

    public void querySkuDetailsAsync(@BillingClient.SkuType final String itemType,
                                     final List<String> skuList, final SkuDetailsResponseListener listener) {
        // Specify a runnable to start when connection to Billing client is established
        Runnable executeOnConnectedService = new Runnable() {
            @Override
            public void run() {
                SkuDetailsParams skuDetailsParams = SkuDetailsParams.newBuilder()
                        .setSkusList(skuList).setType(itemType).build();
                mBillingClient.querySkuDetailsAsync(skuDetailsParams,
                        new SkuDetailsResponseListener() {
                            @Override
                            public void onSkuDetailsResponse(int responseCode,
                                                             List<SkuDetails> skuDetailsList) {
                                listener.onSkuDetailsResponse(responseCode, skuDetailsList);
                            }
                        });
            }
        };

        // If Billing client was disconnected, we retry 1 time and if success, execute the query
        startServiceConnectionIfNeeded(executeOnConnectedService);
    }

    public void startPurchaseFlow(final String skuId, final String billingType) {
        // Specify a runnable to start when connection to Billing client is established
        Runnable executeOnConnectedService = new Runnable() {
            @Override
            public void run() {
                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                        .setType(billingType)
                        .setSku(skuId)
                        .build();
                mBillingClient.launchBillingFlow(mActivity, billingFlowParams);
            }
        };

        // If Billing client was disconnected, we retry 1 time and if success, execute the query
        startServiceConnectionIfNeeded(executeOnConnectedService);
    }

    public void destroy() {
        mBillingClient.endConnection();
    }
}

1 个答案:

答案 0 :(得分:1)

我使用了TrivialDrive示例中的代码。现在它有效。

MainActivity中的

mUpdateListener = new myBillingUpdateListener();
        mBillingManager = new BillingManager(this, getUpdateListener());

@Override
        public void onPurchasesUpdated(List<Purchase> purchaseList) {

            for (Purchase purchase : purchaseList) {
                switch (purchase.getSku()) {
                    case "no_ad":
                        doNotShowAds = true;
                        break;
                }
            }
        }
在BillingManager中:

@Override
    public void onPurchasesUpdated(int resultCode, List<Purchase> purchases) {
        if (resultCode == BillingClient.BillingResponse.OK) {
            for (Purchase purchase : purchases) {
                handlePurchase(purchase);
            }
            mBillingUpdatesListener.onPurchasesUpdated(mPurchases);
        } else if (resultCode == BillingClient.BillingResponse.USER_CANCELED) {
            Log.i(TAG, "onPurchasesUpdated() - user cancelled the purchase flow - skipping");
        } else {
            Log.w(TAG, "onPurchasesUpdated() got unknown resultCode: " + resultCode);
        }
    }