We recently released to our TWA (our app <https://play.google.com/store/apps/details?id=com.coursicle.coursicle&hl=en_US&gl=US>) to customers and on day 1 are experiencing a very consistent issue with Google Play Billing. When we try to call getDetails() on a SKU as well as when we call listPurchases(), we receive a "DOMException: clientAppUnavailable", and the promise fails. Here are the tracebacks:
[image: image (4)] <https://user-images.githubusercontent.com/3255298/247774396-7f33fb3f-da3a-4efd-b109-c0d3c0ee8043.png> [image: image (3)] <https://user-images.githubusercontent.com/3255298/247774381-dad48b4f-2343-4a89-90e7-8d71856618e8.png> We are confident though that Play Services are being initialized: [image: image (2)] <https://user-images.githubusercontent.com/3255298/247774151-af18d5c3-cc7e-45fb-8890-36d038a659a3.png> After a lot of debugging, our current lead is that the issue may be with our Delegation Service. On Android 11, the Delegation Service runs and the extra command handler is registered successfully. On Android 13, the Delegation Service fails to run and a clientAppUnavailable DOM exception is raised. I've attached all of the files we believe are relevant (web_app_manifest.json, AndroidManifest.xml, build.gradle, DelegationService.kt, manifest-server.json) and here is our Javascript for making the purchase: https://pastebin.com/raw/qYhpQiBw. Here's our device information: - Device: Galaxy A03s (working) - OS: Android 11 - Browsers Installed: Chrome - Browser Versions: Chrome 114.0.5735.131 - android-browser-helper library version: 2.4.0 - Device: Galaxy S22 Ultra (not working) - OS: Android 13 - Browsers Installed: Chrome - Browser Versions: Chrome 114.0.5735.130 - android-browser-helper library version: 2.4.0 Here's a comprehensive list of everything we've tried so far: - Clearing the Google Play Store Cache - Incrementing the targetSdkVersion in build.gradle from 33 to 34. - Ensuring the com.android.vending.BILLING permission is added to AndroidManifest.xml - Ensuring that Google Play Services is up to date. - Done a line by line comparison with the PWA billing guide ( https://chromeos.dev/en/publish/pwa-play-billing) It seems like others have encountered this issue as well, although any fix they found did not work for us, and they in general were targeting older SDK versions: - https://stackoverflow.com/questions/74154396/why-does-the-digital-goods-apis-getservice-method-reject-with-clientappunavaila - clientAppUnavailable from getDetails GoogleChromeLabs/bubblewrap#640 (comment) <https://github.com/GoogleChromeLabs/bubblewrap/issues/640#issue-1105007499> Thank you so much for any assistance you can provide. We're really excited about our new PWA and this is the only major issue we've encountered during our conversion from native. -- You received this message because you are subscribed to the Google Groups "Android Developers" group. To unsubscribe from this group and stop receiving emails from it, send an email to android-developers+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/android-developers/b6b8d20c-8ab0-47d0-a0ff-27a87ab90085n%40googlegroups.com.
DelegationService.kt.gradle
Description: Binary data
build.gradle
Description: Binary data
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <!--package="com.coursicle.coursicle" >--> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="com.android.vending.BILLING" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="com.google.android.gms.permission.AD_ID" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <application android:name="CoursicleApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher" android:supportsRtl="true" android:theme="@style/AppTheme" android:manageSpaceActivity="com.google.androidbrowserhelper.trusted.ManageDataLauncherActivity" android:backupAgent=".MyBackupAgent"> <meta-data android:name="com.google.android.backup.api_key" android:value="[redacted]" /> <!-- PWA Stuff --> <meta-data android:name="asset_statements" android:resource="@string/assetStatements" /> <meta-data android:name="web_manifest_url" android:value="@string/webManifestUrl" /> <meta-data android:name="twa_generator" android:value="@string/generatorApp" /> <activity android:name="com.google.androidbrowserhelper.trusted.ManageDataLauncherActivity"> <meta-data android:name="android.support.customtabs.trusted.MANAGE_SPACE_URL" android:value="@string/launchUrl" /> </activity> <!--android:alwaysRetainTaskState="true"--> <activity android:name="LauncherActivity" android:label="@string/launcherName" android:exported="true" android:supportsRtl="true"> <meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL" android:value="@string/launchUrl" /> <meta-data android:name="android.support.customtabs.trusted.STATUS_BAR_COLOR" android:resource="@color/navigationColor" /> <meta-data android:name="android.support.customtabs.trusted.NAVIGATION_BAR_COLOR" android:resource="@color/navigationColor" /> <meta-data android:name="android.support.customtabs.trusted.NAVIGATION_BAR_COLOR_DARK" android:resource="@color/navigationColorDark" /> <meta-data android:name="androix.browser.trusted.NAVIGATION_BAR_DIVIDER_COLOR" android:resource="@color/navigationDividerColor" /> <meta-data android:name="androix.browser.trusted.NAVIGATION_BAR_DIVIDER_COLOR_DARK" android:resource="@color/navigationDividerColorDark" /> <meta-data android:name="android.support.customtabs.trusted.SPLASH_IMAGE_DRAWABLE" android:resource="@mipmap/ic_launcher"/> <meta-data android:name="android.support.customtabs.trusted.SPLASH_SCREEN_BACKGROUND_COLOR" android:resource="@color/backgroundColor"/> <meta-data android:name="android.support.customtabs.trusted.SPLASH_SCREEN_FADE_OUT_DURATION" android:value="@integer/splashScreenFadeOutDuration"/> <meta-data android:name="android.support.customtabs.trusted.FILE_PROVIDER_AUTHORITY" android:value="@string/providerAuthority"/> <!--meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /--> <meta-data android:name="android.support.customtabs.trusted.FALLBACK_STRATEGY" android:value="@string/fallbackType" /> <meta-data android:name="android.support.customtabs.trusted.SCREEN_ORIENTATION" android:value="@string/orientation"/> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE"/> <data android:host="daniel.coursicle.com" android:scheme="https" /> </intent-filter> </activity> <activity android:name="com.google.androidbrowserhelper.trusted.FocusActivity" /> <activity android:name="com.google.androidbrowserhelper.trusted.WebViewFallbackActivity" android:configChanges="orientation|screenSize" /> <provider android:name="androidx.core.content.FileProvider" android:authorities="@string/providerAuthority" android:grantUriPermissions="true" android:exported="false"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/filepaths" /> </provider> <service android:name=".DelegationService" android:enabled="true" android:exported="true"> <meta-data android:name="android.support.customtabs.trusted.SMALL_ICON" android:resource="@mipmap/ic_launcher" /> <intent-filter> <action android:name="android.support.customtabs.trusted.TRUSTED_WEB_ACTIVITY_SERVICE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <!-- <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> --> </service> <activity android:name="com.google.androidbrowserhelper.playbilling.provider.PaymentActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:configChanges="keyboardHidden|keyboard|orientation|screenLayout|screenSize" android:exported="true"> <intent-filter> <action android:name="org.chromium.intent.action.PAY" /> </intent-filter> <meta-data android:name="org.chromium.default_payment_method_name" android:value="https://play.google.com/billing" /> </activity> <!-- This service checks who calls it at runtime. --> <service android:name="com.google.androidbrowserhelper.playbilling.provider.PaymentService" android:exported="true" > <intent-filter> <action android:name="org.chromium.intent.action.IS_READY_TO_PAY" /> </intent-filter> </service> </application> </manifest>
manifest-server.json
Description: application/json
web_app_manifest.json
Description: Binary data