DEV Community

Olivia Sung for Amazon Appstore Developers

Posted on • Updated on

Porting Your Android App from Google Play Billing to Amazon (While Enjoying Pizza)

If you have an existing Android App that uses the Google Play Billing Library for in-app purchases (IAP) and subscriptions, you can use the Appstore Billing Compatibility (ABC) SDK to port it to the Amazon Appstore. Porting your app to the Amazon Appstore offers you a great opportunity to connect with engaged customers around the world — to date, there have been more than 200 million Fire TV devices sold globally.

Similar to the Google Play Billing Library versions 4.0 and 5.0, the Amazon Appstore Billing Compatibility SDK supports consumable, entitlement, and subscription IAPs. In this article, we'll walk through the step-by-step instructions to integrate the Appstore Billing Compatibility SDK into your app. I will use our Hello Pizza ordering app for the purposes of this article (because ordering and eating pizza is one of my favorite things to do when I'm not building apps).

Let’s dive in and get started. I’ve already built a Hello Pizza app that uses the Google Play Billing Library. Before porting the app to the Amazon Appstore, let’s go through a checklist of the items we need.

Checklist — what you’ll need to get started to port your Android app to the Amazon Appstore

Getting started is simple. Below are the three things you’ll need to port your app to the Amazon Appstore:

  1. An Android app that uses versions 4.0 or 5.0 of the Google Play Billing Library.
  2. An Amazon Developer Console Account (If you don’t have one, you can get it here.)

The Amazon Appstore Billing Compatibility SDK (you can download the latest version here — extract the zip file and copy the jar file).

Step 1: Integrate the Amazon Appstore SDK 📥

A. You’ve downloaded the Appstore Billing Compatibility SDK includes the JAR file and API documentation. Now, add the appstore-billing-compatibility-4.1.0.jar file to your app's libs folder.

Image description

B. Next, update your app's build.gradle file to include the SDK dependency:

Here’s the familiar looking code you would have for your Android app.

implementation(libs.google.billing)

But change this to

dependencies {
    implementation files('libs/appstore-billing-compatibility-4.1.0.jar')
}
Enter fullscreen mode Exit fullscreen mode

C. Now, sync your project to resolve the dependency.

Step 2: Configure Your App 🔧

It’s time to configure your app!

A. To get started, log in to the Amazon Developer Console and navigate to your app's page.

Image description

B. Generate a public key for your app and download the AppstoreAuthenticationKey.pem file. You can find more information here.

Image description

Image description

C. Next, copy the PEM file to your app's src/main/assets folder.

Image description

D. Update your AndroidManifest.xml file to include the BillingResponseReceiver. Remember, if your app targets Android 12 or higher, you must explicitly set android:exported to true in the MainActivity and ResponseReceiver.

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:theme="@style/Theme.HelloPizza">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<receiver
    android:name="com.amazon.device.iap.billingclient.api.BillingResponseReceiver"
    android:exported="true"
    android:permission="com.amazon.inapp.purchasing.Permission.NOTIFY">
    <intent-filter>
        <action android:name="com.amazon.inapp.purchasing.NOTIFY" />
    </intent-filter>
</receiver>
Enter fullscreen mode Exit fullscreen mode

E. Update your app's import statements to use the Appstore Billing Compatibility SDK classes. Replace com.android.billingclient.api with the com.amazon.device.iap.billingclient.api).

F. Add your app IAP items to the Amazon Appstore Developer Console following the instructions here. This will allow you to do important things like charge for your pizza, and also the noble things like offer your pizza at a discount.

Image description

Image description

Step 3: Initialize the BillingClient 🚀

Now that you’ve configured your app, it’s time to initialize a BillingClient instance in your app. This is similar to how you would initialize a billing instance with Google Play Billing. The syntax to initalize the billing clients is the same with the two SDKs.

In Google Play Billing:

private val billingClient = BillingClient.newBuilder(application)
    .setListener(this)
    .enablePendingPurchases()
    .build()
Enter fullscreen mode Exit fullscreen mode

For the ABC SDK:

private val billingClient = BillingClient.newBuilder(application)
    .setListener(this)
    .enablePendingPurchases()
    .build()
Enter fullscreen mode Exit fullscreen mode

Step 4: Connect to the Amazon Appstore 🔗

Unlike Google Play Billing, the Amazon Appstore doesn't require you to maintain a connection. All you have to do is call startConnection() on your BillingClient instance:

In Google Play Billing:

class GoogleIAPDataSource : BillingClientStateListener {
...
    init {
        billingClient.startConnection(this)
    }
...
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        when (billingResult.responseCode) {
            BillingClient.BillingResponseCode.OK -> {
                reconnectMilliseconds = RECONNECT_TIMER_START_MS
                defaultScope.launch {
                    querySkuDetailsAsync()
                    refreshPurchasesAsync()
                }
            }

            else -> {
                onBillingServiceDisconnected()
            }
        }
    }    

    override fun onBillingServiceDisconnected() {
        reconnectMilliseconds = (reconnectMilliseconds * 2).coerceAtMost(RECONNECT_TIMER_MAX_MS)
        billingClient.startConnection(this)
    }
}
Enter fullscreen mode Exit fullscreen mode

In ABC SDK:

override fun onBillingSetupFinished(billingResult: BillingResult) {
    when (billingResult.responseCode) {
        BillingClient.BillingResponseCode.OK -> {
            reconnectMilliseconds = RECONNECT_TIMER_START_MS
            defaultScope.launch {
                querySkuDetailsAsync()
                refreshPurchasesAsync()
            }
        }

        else -> {
            onBillingServiceDisconnected()
        }
    }
}


override fun onBillingServiceDisconnected() {
    reconnectMilliseconds = (reconnectMilliseconds * 2).coerceAtMost(RECONNECT_TIMER_MAX_MS)
    billingClient.startConnection(this)
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Query Product Details 🔍

To retrieve the details for your product, you can use either the queryProductDetailsAsync() or querySkuDetailsAsync() method. The syntax is the same between ABC and Google Play Billing.

val inAppSkuDetailsParams = SkuDetailsParams.newBuilder()
    .setType(BillingClient.SkuType.INAPP)
    .setSkusList(knownInAppSKUs)
    .build()
billingClient.querySkuDetailsAsync(inAppSkuDetailsParams) { result, details ->
    onSkuDetailsResponse(result, details)
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Launch the Purchase Flow 🚀

To start a purchase, simply call the launchBillingFlow() method with a BillingFlowParams object containing the product details. The syntax is the same between ABC and Google Play Billing.

val billingFlowParams = BillingFlowParams.newBuilder()
    .setSkuDetails(skuDetails)
    .build()
val billingResult = billingClient.launchBillingFlow(activity!!, billingFlowParams)
Enter fullscreen mode Exit fullscreen mode

Note: The Appstore Billing Compatibility SDK allows only one product per purchase.

Step 7: Process Purchases 💰

After a successful purchase, process it in your PurchasesUpdatedListener's onPurchasesUpdated() method.

 override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
    when (billingResult.responseCode) {
        BillingClient.BillingResponseCode.OK -> purchases?.let { processPurchaseList(it, null) }
        else -> {}
    }
    defaultScope.launch {
        _billingFlowInProcess.emit(false)
}
Enter fullscreen mode Exit fullscreen mode

For consumables, call consumeAsync() to acknowledge delivery and mark the item as consumed.

billingClient.consumeAsync(consumeParams) { billingResult, _ ->
    purchaseConsumptionInProcess.remove(purchase)
    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
        defaultScope.launch {
            _purchaseConsumedFlow.emit(purchase.skus)
        }
        purchase.skus.forEach { sku ->
            setSkuState(sku, SkuState.UNPURCHASED)
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

For entitlements, use acknowledgePurchase() to acknowledge delivery.

Step 8: Fetch Purchases 🛒

To retrieve a user's purchases, call queryPurchasesAsync().

billingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP) { billingResult, purchases ->
    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
        processPurchaseList(purchases, knownInAppSKUs)
    }
}

billingClient.queryPurchasesAsync(BillingClient.SkuType.SUBS) { billingResult, purchases ->
    if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
        processPurchaseList(purchases, listOf(knownSubscriptionSKUs))
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 9: Test Your App 🧪

To test your app's integration with the Appstore Billing Compatibility SDK, you can use the Live App Testing to test your app in a live production environment with a select group of users. To set up Live App Testing for your app follow the steps here.

Discount Subscription Entitlement
Image description Image description Image description

Important notes

  • It’s easy to forget to place the file AppstoreAuthenticationKey.pem in the correct directory You should double check you performed all the steps in the Configure Your App 🔧 section above.
  • Check that the SKUs used in your app are the same that you defined in the Amazon Appstore Console (See the official guide)

Conclusion 🎉

If you’ve followed the steps above carefully, your app should be compatible with In-app purchasing on the Amazon Appstore. Here’s more resources to help ensure that you are getting the most bang for your buck from your development efforts on the Amazon Appstore. I hope you enjoyed this article. As for me, writing this demo has made me hungry. I’m now going to power off for the evening and get some pizza.

Stay updated

For the latest Amazon Appstore developer news, product releases, tutorials, and more:
📣 Follow @AmazonAppDev and our team on Twitter
📺 Subscribe to our YouTube channel
📧 Sign up for the Developer Newsletter

Related resources

Top comments (0)