Android Billing库v4升级:如何将BillingFlowParams的sku()替换为setSkuDetails()
Google Play Billing v4 setSkuDetails 支付流程配置方案
核心逻辑说明
Billing v4 要求必须通过querySkuDetailsAsync接口从Google Play查询获取SkuDetails对象,不可自行构造,再将该对象传入setSkuDetails方法完成支付参数配置。
实现步骤
1. 定义全局变量
先定义商品ID常量和存储SkuDetails的全局变量:
// 替换为你在Google Play后台配置的对应商品ID private static final String SKU_MONTHLY = "monthly_sub_id"; private static final String SKU_YEARLY = "yearly_sub_id"; private static final String SKU_ONE_TIME = "one_time_inapp_id"; // 存储查询返回的商品详情对象 private SkuDetails monthlySkuDetails, yearlySkuDetails, oneTimeSkuDetails; private BillingClient mBillingClient;
2. 新增SkuDetails查询方法
封装统一的商品查询方法:
private void querySkuDetails(String skuType, List<String> skuList) { SkuDetailsParams params = SkuDetailsParams.newBuilder() .setSkusList(skuList) .setType(skuType) .build(); mBillingClient.querySkuDetailsAsync(params, (billingResult, skuDetailsList) -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) { for (SkuDetails skuDetails : skuDetailsList) { String sku = skuDetails.getSku(); if (SKU_MONTHLY.equals(sku)) { monthlySkuDetails = skuDetails; // 可在此处调用skuDetails.getPrice()获取商品价格展示到UI } else if (SKU_YEARLY.equals(sku)) { yearlySkuDetails = skuDetails; } else if (SKU_ONE_TIME.equals(sku)) { oneTimeSkuDetails = skuDetails; } } } }); }
3. 初始化成功后触发商品查询
修改onBillingSetupFinished回调逻辑,替换原有三个getPrices方法:
@Override public void onBillingSetupFinished(@NonNull BillingResult billingResult) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { // 查询订阅类商品 querySkuDetails(BillingClient.SkuType.SUBS, Arrays.asList(SKU_MONTHLY, SKU_YEARLY)); // 查询一次性内购商品 querySkuDetails(BillingClient.SkuType.INAPP, Collections.singletonList(SKU_ONE_TIME)); } }
4. 支付点击事件中传入SkuDetails
修改continue_button的点击逻辑,给setSkuDetails传入对应商品的SkuDetails对象,增加非空判断避免崩溃:
continue_button.setOnClickListener(view -> { if (select_radio_one.getVisibility() == View.VISIBLE) { if (monthlySkuDetails == null) { Toast.makeText(MainActivity.this, "商品信息加载中,请稍后重试", Toast.LENGTH_SHORT).show(); return; } BillingFlowParams flowParams = BillingFlowParams.newBuilder() .setSkuDetails(monthlySkuDetails) .build(); mBillingClient.launchBillingFlow(MainActivity.this, flowParams); brandDialogInAppPurchase.dismiss(); } else if (select_radio_two.getVisibility() == View.VISIBLE) { if (yearlySkuDetails == null) { Toast.makeText(MainActivity.this, "商品信息加载中,请稍后重试", Toast.LENGTH_SHORT).show(); return; } BillingFlowParams flowParams = BillingFlowParams.newBuilder() .setSkuDetails(yearlySkuDetails) .build(); mBillingClient.launchBillingFlow(MainActivity.this, flowParams); brandDialogInAppPurchase.dismiss(); } else if (select_radio_three.getVisibility() == View.VISIBLE) { if (oneTimeSkuDetails == null) { Toast.makeText(MainActivity.this, "商品信息加载中,请稍后重试", Toast.LENGTH_SHORT).show(); return; } BillingFlowParams flowParams = BillingFlowParams.newBuilder() .setSkuDetails(oneTimeSkuDetails) .build(); mBillingClient.launchBillingFlow(MainActivity.this, flowParams); brandDialogInAppPurchase.dismiss(); } else { Toast.makeText(MainActivity.this, "未选择任何商品", Toast.LENGTH_SHORT).show(); } });
注意事项
- 所有SkuDetails对象必须通过官方
querySkuDetailsAsync接口获取,自行构造的对象会触发支付错误 - 必须在BillingClient初始化完成(即onBillingSetupFinished返回OK)之后再调用商品查询接口
- 调用支付前必须对SkuDetails做非空判断,避免商品未加载完成时用户点击导致崩溃
内容的提问来源于stack exchange,提问作者Maan Chaudhary
相关产品推荐
相关产品推荐

