We have a TWA/PWA in the Play store. We want to start selling Play subscriptions through our app.
We followed the Chrome Developer guides to implementing the necessary steps in the Android project and the PWA. We also checked our code against the Android Browser Helper demo and the code generated by the latest Bubblewrap version. (We did not use Bubblewrap to generate our project, however.) As far as we can see, our functionality is equivalent. We tried bundling the same versions of the androidbrowserhelper:androidbrowserhelper
and androidbrowserhelper:billing
dependencies as Bubblewrap. We also tried downgrading to those used in TWA Play Billing Demo.
With these prerequisites (hopefully) in place in the Android wrapper, we configured a subscription product (with a base plan) in the Play console.
Now we are trying to test fetching product details using the Digitial Goods API, following the examples linked above.
We can successfully detect the availability of the API in our context. We also find the call to window.getDigitalGoodsService('https://play.google.com/billing')
successfully resolves.
We await the service object before calling service.getDetails([ 'our_sku' ])
, but this call rejects with an error clientAppUnavailable
.
We cannot find any clarification related to this error, either in resources about Android Browser Helper nor the (Android) Google Play Billing Library.
The following snippets illustrate the relevant code (IMO) in our codebases.
build.gradle
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.4.0'
implementation 'com.google.androidbrowserhelper:billing:1.0.0-alpha09'
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
<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>
DigitalGoodsDelegationService.java
import com.google.androidbrowserhelper.playbilling.digitalgoods.DigitalGoodsRequestHandler;
import com.google.androidbrowserhelper.trusted.DelegationService;
public class DigitalGoodsDelegationService extends DelegationService{
@Override
public void onCreate() {
super.onCreate();
registerExtraCommandHandler(new DigitalGoodsRequestHandler(getApplicationContext()));
}
}
PWA
const SERVICE_ID = 'https://play.google.com/billing';
window.getDigitalGoodsService(SERVICE_ID)
.then((service) => {
if (!service) throw new Error(ERROR_MESSAGES.noPlayBilling);
// eslint-disable-next-line no-console
console.log('Got service');
return service.getDetails(SKUS);
})
.then(products => {
if (!products || !products.length) {
throw new Error(ERROR_MESSAGES.noProducts);
}
...
})
.catch(err => {
...
});
We resolved the error by compiling against an upgraded version of the Android API. (Before, compileSdkVersion
was set to 30
in our module-level build.gradle
. We upgraded this to 31
.)