You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Billing Library v4调用querySkuDetailsAsync无法返回SKU详情问题求助

排查Billing Library v4中querySkuDetailsAsync回调不触发的问题

结合你描述的情况(v2版本正常、应用已发布、SKU均有效但回调无响应),我整理了几个升级到v4后容易踩的坑,帮你定位问题:

1. 先确认Billing服务是否真的初始化成功

你当前的代码只在初始化成功时打印日志,但有可能isBillingResultSuccessful方法的判断逻辑在v4下失效了——比如v4新增了响应码,或者你对BILLING_UNAVAILABLE这类状态的处理有误。

建议先修改onBillingSetupFinished,不管成功失败都打印完整的BillingResult信息:

@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
    int responseCode = billingResult.getResponseCode();
    String debugMsg = billingResult.getDebugMessage();
    activity.logInfo("Billing setup result: code=%d, msg=%s", responseCode, debugMsg);
    
    if (isBillingResultSuccessful(billingResult, CONNECTING)) {
        activity.logInfo("Successfully connected to billing service");
        fetchSkuDetails();
    } else {
        activity.logError("Billing setup failed: %d - %s", responseCode, debugMsg);
        activity.hideProgressBar(); // 避免进度条一直挂着
    }
}

如果发现初始化其实没成功(比如返回3即BILLING_UNAVAILABLE),那可能是设备Google Play服务版本过低,或者当前地区不支持内购。

2. 检查BillingClient的生命周期是否正确管理

Billing Library v4对客户端实例的生命周期要求更严格,如果你的BillingClient是局部变量(比如在某个方法内临时创建),或者在回调触发前被GC回收了,就会导致回调永远不执行。

确保:

  • BillingClient是Activity的成员变量(全局持有)
  • 在Activity的onDestroy方法中调用billingClient.endConnection()释放资源
  • 尽量在主线程初始化BillingClient,避免子线程带来的线程同步问题

3. 验证SKU参数的准确性

虽然你说SKU都存在,但v4对参数的校验更严格,几个容易忽略的点:

  • 大小写敏感:Google Play的SKU是区分大小写的,v2可能兼容了大小写错误,但v4会直接过滤不匹配的SKU,甚至导致整个请求失败
  • SKU类型匹配:确认你传入的所有SKU都是INAPP类型(非订阅),如果混了一个订阅SKU,会导致请求异常
  • 参数拼接错误:打印skuList的所有元素,确认PRODUCT_ID_PREFIX + i的结果和Google Play后台的SKU完全一致(比如有没有多下划线、少数字)

可以先简化测试:把skuList改成只包含一个确定有效的INAPP SKU,看看能不能触发回调。如果可以,再逐个添加其他SKU,找出可能有问题的那个。

4. 检查应用签名与Google Play后台的一致性

升级到v4后,部分开发者遇到过签名验证更严格的情况。如果你的应用在升级过程中更换了签名证书(比如从调试签名换成发布签名,或者使用了App Signing by Google Play),要确保:

  • 本地测试用的签名和Google Play后台配置的签名一致
  • 如果开启了App Signing,要把上传密钥的SHA-1也添加到Google Play的应用签名配置中

5. 排查回调线程的潜在问题

虽然querySkuDetailsAsync的回调默认会切换到主线程,但如果你的activity实例在回调触发前已经销毁(比如用户切到后台),可能导致回调无法执行。可以在回调中添加空指针判断:

(billingResult, skuDetailsList) -> {
    if (activity.isFinishing() || activity.isDestroyed()) {
        activity.logWarn("Activity destroyed, skipping SKU response");
        return;
    }
    // 后续逻辑
}

最后,修改fetchSkuDetails的回调,强制打印所有结果(包括skuDetailsList为null的情况),这样即使失败也能看到具体错误:

(billingResult, skuDetailsList) -> {
    activity.hideProgressBar();
    int responseCode = billingResult.getResponseCode();
    String debugMsg = billingResult.getDebugMessage();
    int listSize = skuDetailsList != null ? skuDetailsList.size() : -1;
    activity.logInfo("SKU response received: code=%d, msg=%s, listSize=%d", responseCode, debugMsg, listSize);
    
    if (isBillingResultSuccessful(billingResult, RETRIEVING_PRODUCTS)) {
        addProducts(skuDetailsList);
        skuResponseListener.onSkuDetailsResponse(skuDetailsList);
    } else {
        activity.logError("Fetch SKU failed: %d - %s", responseCode, debugMsg);
    }
}

内容的提问来源于stack exchange,提问作者Egemen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 16:49:07