This is the second chapter of our subscription guide for Android series. Previously, we’ve covered how to create and configure in-app subscriptions in Google Play Console, going the full distance in examining every tool Google has to offer. Be sure to check it out.
In this article, we will tell you how to integrate the Google Play Billing Library into your app and start selling products. We’ll dive into the more technical side of things and extract everything we consider essential.
Imagine you’ve created an app and want to monetize it. If you wish to upload it to the Google Play Store (which most Android developers do), your monetization flow should use Google’s own billing solution, namely Google Play Billing Library. Google uses it to make money by taxing developers’ transactions.
Last March, Google halved the usual 30% tax for the first $1 million of revenue developers earn using the Play billing system each year. Note that Google’s new approach is slightly different from Apple, which drops its commission from companies that generate no more than $1 million in revenue through the company’s platform.
Note that you should use the Library if your app sells digital goods and services, like in-app currency in games or digital subscriptions. Apps that sell physical goods and services, e.g., Amazon Shopping or Uber Eats, shouldn’t use the Billing Library.
Starting August 2021, you can’t upload a new app to Google Play with a billing solution rather than Billing Library ver. 3. By November all updates to existing apps must use Billing Library version 3 or newer.
Let’s get terminology out of the way first.
Here's a typical purchase flow for a one-time purchase or a subscription.
Subscriptions automatically renew until they are cancelled. A subscription can go through the following states:
Google Play tracks products and transactions using purchase tokens and Order IDs. Let’s directly take terms from Google:
Order IDs are created every time a financial transaction occurs. Purchase tokens are generated only when a user completes the purchase flow.
For one-time products, every purchase creates a new purchase token. Most purchases also generate a new Order ID, except when the user isn’t charged at all, as described in Google’s Promo codes.
For subscriptions, an initial purchase creates a purchase token and an Order ID. For each continuous billing period, the purchase token stays the same and a new Order ID is issued.
The first step to integrating with Google Play's billing system is to add the library to your app and initialize a connection.
Add the Google Play Billing Library dependency to your app's build.gradle file:
If you want to use coroutines, you can integrate dependency Play Billing Library KTX:
Every code chunk down below are written in Kotlin. Check with Google’s official guide to find code written in Java.
BillingClient is the main interface for communication between the Google Play Billing Library and the rest of your app. It provides convenient methods for many common billing operations. Once you've added a dependency to the Google Play Billing Library, you'll need to initialize a BillingClient instance.
To create a BillingClient, use newBuilder(). To receive updates on purchases, you must also call setListener(), passing a reference to a PurchasesUpdatedListener. This listener receives updates for all purchases in your app.
Once you created a BillingClient, you have to establish a connection to Google Play. This is how you do it:
The Google Play Billing Library returns errors in the form of BillingResult. A BillingResult contains a BillingResponseCode, which categorizes possible billing-related errors that your app may encounter. Let’s say you receive a SERVICE_DISCONNECTED error code, so your app should reinitialize the connection with Google Play. Additionally, a BillingResult contains a debug message, which is useful during development to diagnose errors.
Note: It's strongly recommended that you implement your own connection retry logic and override the onBillingServiceDisconnected() method. Make sure you maintain the BillingClient connection when executing any method.
Once you have established a connection to Google Play, you are ready to query your available products and display them to your users. We’ve already covered how you create products in the first chapter.
You can find an example of the request on product info below:
You should request info on subscriptions and info on one-time purchases separately by using constants SkuType.SUBS and SkuType.INAPP, accordingly.
The Library stores query results in a List of SkuDetails objects. After that, you can call a variety of methods on each SkuDetails object in the list to view relevant information about an in-app product like its price or description. To view the available product detail information, see the list of methods in the SkuDetails class.
To start a purchase request from your app, call the launchBillingFlow() method from your app's main thread, as shown below.
If responseCode equals to BillingResponseCode of OK, system displays the Google Play purchase screen:
Google Play calls a callback on PurchasesUpdatedListener that we have already covered in the “Initialize a Billing Client” section. Let’s fill it with code:Processing purchases
Your app should process a purchase in the following way:
Once you've verified the purchase, your app is ready to grant entitlement to the user. After granting entitlement, your app must then acknowledge the purchase. The process to grant entitlement and acknowledge the purchase depends on whether the purchase is a non-consumable, a consumable, or a subscription.
When talking about consumables, consumeAsync() method fulfills the acknowledgment requirement and shows that your app has granted entitlement to the user. This method also enables your app to make the one-time product available for purchase again.
To indicate that a one-time product has been consumed, call consumeAsync() and include the purchase token that Google Play should make available for repurchase.
The following example illustrates consuming a product using the associated purchase token:
Before acknowledging a purchase, your app should check whether it was already acknowledged by using the isAcknowledged() method in the Google Play Billing Library. If you don’t have verification on your own back-end, then the only way you can acknowledge non-consumable purchases and subscriptions is BillingClient.acknowledgePurchase() from the Billing Library.
The following example shows how to acknowledge a purchase using the Google Play Billing Library:
Listening to purchase updates using a PurchasesUpdatedListener is not sufficient to ensure your app processes all purchases. It's possible that your app might not be aware of all the purchases a user has made. Here are some scenarios where your app could lose track or be unaware of purchases:
To handle such situations, make sure that your app calls BillingClient.queryPurchases() in your onResume() and onCreate() methods.
Remember, in the “Initialize a BillingClient” section we've added enablePendingTransaction()? Google Play supports pending transactions, which require one or more additional steps between two stages: when a user initiates a purchase and when the payment method for the purchase is processed. Your app shouldn’t grant entitlement to such purchases until Google notifies you that it received the payment.
If your app is in the foreground and the purchase status has changed from “Pending” to “Purchased”, a callback on PurchasesUpdatedListener gets called again. In this case, you can take all necessary actions like in handlePurchase(). In this example, you do nothing when the purchase status is “Pending” as you should acknowledge a purchase only when the state is “Purchased”, and you can’t acknowledge when it’s “Pending”. The three-day acknowledgment window begins only when the purchase state transitions to “Purchased”.
Your app should also call queryPurchases() in your app's onResume() and onCreate() methods to handle purchases that have transitioned to the PURCHASED state while your app is not running.
This was a brief overview of how to handle purchases on Android devices. In the next (and last) chapter we will cover what you can do with your own back-end.