TWA中调用Digital Goods API的getDetails报clientAppUnavailable错误
问题背景
我们有一款已上架Play商店的TWA/PWA应用,计划通过该应用售卖Play订阅服务。已完成以下操作:
- 遵循Chrome开发者指南配置Android项目与PWA
- 对比Android Browser Helper示例及Bubblewrap生成代码,尝试匹配依赖版本、降级至TWA Play Billing Demo使用的版本
- 在Play控制台配置含基础套餐的订阅产品
测试Digital Goods API时:
- 可检测到API可用,成功调用
window.getDigitalGoodsService('https://play.google.com/billing')获取服务对象 - 调用
service.getDetails([ 'our_sku' ])时返回clientAppUnavailable错误,且在Android Browser Helper及Google Play Billing Library资源中未找到该错误的官方说明
可能原因与解决步骤
1. 缺失Play Billing Library依赖
com.google.androidbrowserhelper:billing扩展依赖Google Play Billing Library,但你的build.gradle中未显式声明该依赖,可能导致Billing客户端初始化失败。
解决:在dependencies块中添加对应版本的Billing Library依赖:
implementation 'com.android.billingclient:billing:5.2.0'
(注:1.0.0-alpha09版本的billing扩展建议搭配4.0.0+的Billing Library,稳定版billing扩展可搭配5.x版本)
2. 未声明BILLING权限
Android应用需要明确声明BILLING权限才能访问Play Billing服务,否则会导致服务调用失败。
解决:在AndroidManifest.xml根节点下添加权限声明:
<uses-permission android:name="com.android.vending.BILLING"/>
3. 依赖版本不兼容
你的项目中androidbrowserhelper版本为2.4.0,而billing扩展为1.0.0-alpha09,两者版本可能不匹配,导致内部调用逻辑冲突。
解决:调整为匹配的稳定版本组合:
// 使用稳定版依赖组合 implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.5.0' implementation 'com.google.androidbrowserhelper:billing:1.0.0'
4. Play控制台配置未生效
订阅产品的配置可能未正确关联应用或未发布到可测试的轨道,导致API无法获取商品信息。
解决:
- 确认订阅产品的包名与应用包名完全一致
- 将订阅产品发布到内部测试或封闭测试轨道(不能仅停留在草稿状态)
- 将测试设备使用的Google账号添加到Play控制台的许可测试列表中
5. TWA可信验证未通过
Digital Goods API要求TWA应用与PWA域名通过assetlinks.json完成可信关联,否则会限制API的正常调用。
解决:
- 检查
assetlinks.json文件是否正确放置在PWA域名的.well-known目录下 - 确认文件内容中的应用签名指纹、包名与Play商店上架的应用信息完全匹配
- 验证关联有效性(可通过Google官方工具确认)
6. 测试环境不符合要求
直接通过Android Studio运行安装的TWA应用可能无法正常调用Play Billing服务,必须通过Play商店渠道安装。
解决:
- 将应用上传到Play控制台的内部测试轨道
- 使用测试账号在测试设备上安装该测试版本应用后再进行API测试
补充代码示例
修改后的build.gradle依赖块:
dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.5.0' implementation 'com.google.androidbrowserhelper:billing:1.0.0' implementation 'com.android.billingclient:billing:5.2.0' implementation 'androidx.appcompat:appcompat:1.3.1' implementation 'io.sentry:sentry-android:6.1.2' implementation platform('com.google.firebase:firebase-bom:30.1.0') implementation 'com.google.firebase:firebase-messaging' implementation 'com.google.firebase:firebase-firestore' }
修改后的AndroidManifest.xml(添加权限):
<uses-permission android:name="com.android.vending.BILLING"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.TwaTest"> <service android:name=".DigitalGoodsDelegationService" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </service> <activity android:name=".LauncherActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> <meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL" android:value="https://your-pwa-domain.com"/> </activity> </application>
内容的提问来源于stack exchange,提问作者Robin Howells

