Google Play Billing Library on Android: That time I had to add payments to the app

Danilo Arcadipane
7 min readDec 7, 2020


How many times, during the development of an app, have you found yourself faced with the thousands of articles, links and questions on stackoverflow, regarding Billing?
How many times have you had to deploy the app to find out if everything was correct or if everything worked correctly?
How many times have you said “enough, I will not pay, the guides are all crap!”?
Me many times, but I hope not to be included in one of those mentioned above :-).

The biggest problem is not implementing the payment method, but understanding what to do step by step to make sure everything works correctly.

What I will try to do in this article will be to enclose in a single document the steps to follow in order to add a payment method within your app, using Android Studio as the IDE and Kotlin as the programming language.
Another key point is the following:
I will focus in particular on consumables and how to “consume” them. Well then, we agree. Let’s begin.

Step 1: Create A Google Play Developer Account

In order to implement payments in the app, we will first need to create a Google Play developer account.
Note: by the time of speaking Google Play charges a $25 one-time developer fee.

  1. Go to
  2. Click Create an Account.

3. Fill out the form then click Next Step.

4. Click Back to Google Play Developer Console.

5. Select the Google Play Developer distribution agreement check-box to acknowledge your agreement, and click Continue to payment to pay the one-time $25 fee.

6. Enter your payment information, and click Accept and continue.

7. You will receive an email from Google notifying you when your account is ready to be activated.
Note: This process can take up top a week.

8. Activate your account.

Congratulations, you can now submit your app to the Google Play store. Enjoy!!! :-)

Step 2: User Permission

We create the app we want to publish from Android Studio. It doesn’t matter what our app looks like, we’ll think about that later.
The most important thing now is to activate in-app purchases on the Android Studio side and publish the app from the Google Play Console, before proceeding.

Then open your Manifest and add the following line:

<uses-permission android:name="" />

Step 3: Create and publish an App in the Google Play Developer Console

Go back to the Google Play Console to be able to publish it in the store. On this point, creating an app is really very intuitive.

But before starting two small notes:

Step 4: Add your personal in-app products

Once the app has been published with the billing permissions inside the bundle/apk we will see the “products” section active where it will be possible to set the price of the app (if we want our app to be paid), the in-app products and subscriptions.
In this guide I will focus on the second, the in-app product.

To enable in-app product for your app, do the following:

  1. Open the Google Play Console.
  2. Select your app.
  3. Go to Products > In-app product.

Once you have clicked on “in-app products” it’s time to add all the consumables that we will use within our application.

Click on create product, enter your product ID, product details and price and then click on save at the bottom right.

Once created you should see something like this:

Note: Once the product has been saved, you will no longer be able to change its ID. This is important for two reasons: the first is that the product ID is the element that on the code side (Android Studio side) we will go to fetch to continue with the payment steps, so my advice is to think first about which ID associated with each product.

Step 5: Integrate the Google Play Billing Library into your app

If we have done everything correctly now we just need to implement everything in the app, so now some code :-).

Let’s add the dependencies we need in the gradle:

5.1 Initialize a BillingClient & Establish a connection to Google Play

Once you’ve added a dependency on the Google Play Billing Library, you need to initialize a BillingClient instance. Use newBuilder() to create a BillingClient.

private lateinit var billingClient: BillingClientbillingClient = BillingClient.newBuilder(Dodgers.context!!)

5.2 Implement PurchasesUpdatedListener to receive updates on purchases

override fun onPurchasesUpdated(
billingResult: BillingResult,
purchases: MutableList<Purchase>?
) {
//TODO: not implemented}

5.3 Establish a connection to google play using startConnection()

billingClient.startConnection(object : BillingClientStateListener {
override fun onBillingSetupFinished(billingResult: BillingResult) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// The BillingClient is setup successfully
} else {
skuDetailsList = mutableListOf()

override fun onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
Log.e(TAG, "error")

Now we need to call theloadAllSKUs() function. If BillingClient has been configured correctly we need to download the list of items we have previously added from in-app products from our Google Play Console (STEP 4).

Define new SKUlist

private val skuList: List<String> = listOf(

Then pass your newly created list to the .setSkusList () method to confirm that your list is contained in the one implemented in the Google Play Console

private var skuDetailsList: MutableList<SkuDetails> = mutableListOf()
private fun loadAllSKUs() = if (billingClient.isReady) {
val params = SkuDetailsParams
billingClient.querySkuDetailsAsync(params) { billingResult, skuDetailsList ->
// Process the result.
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && skuDetailsList!!.isNotEmpty()) {
this.skuDetailsList = skuDetailsList
} else this.skuDetailsList = mutableListOf()
} else {
println("Billing Client not ready")

5.4 Launch the purchase flow

if (skuDetailsList.isNotEmpty()) {
val skuDetails = skuDetailsList.first { it.sku == myItem .sku }
val billingFlowParams = BillingFlowParams
billingClient.launchBillingFlow(requireActivity(), billingFlowParams)
} else {
showSnackBar("Error | sku list is empty")

5.5 Handle possible response codes

Once the action is initiated, we need to manage the response through onPurchasesUpdated() method like below:

override fun onPurchasesUpdated(
billingResult: BillingResult,
purchases: MutableList<Purchase>?
) {
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK && purchases != null) {
for (purchase in purchases) {
acknowledgePurchase(purchase, purchase.sku)
} else if (billingResult.responseCode == BillingClient.BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
Log.e(TAG, "User Canceled action")
} else {
// Handle any other error codes.
Log.e(TAG, "An error occurred handling code")

To acknowledge non-consumable purchases, use either BillingClient.acknowledgePurchase() from the Billing library. This can be useful when the selected item is unique and cannot be bought again

private fun acknowledgePurchase(purchase: Purchase, sku: String) {
val params = AcknowledgePurchaseParams.newBuilder()
billingClient.acknowledgePurchase(params) { billingResult ->
val responseCode = billingResult.responseCode
val debugMessage = billingResult.debugMessage

(Dispatchers.Main + exceptionHandler).launch {
val skuItem = Gem.values().find { it.sku == sku }
// Do something with skuItemSelected and purchased

Done. the item selected on click and the purchase action was successful, you do not need anything else but to manage the action after the purchase in your app as you see fit. If, on the other hand, you want the item to be available again for a new purchase then you will have to consume the same as soon as the user has purchased it and this means calling the method consumeItemPurchased():

private fun consumeItemPurchased(purchase: Purchase) {
// Verify the purchase.
// Ensure entitlement was not already granted for this purchaseToken.
// Grant entitlement to the user.
val consumeParams =

billingClient.consumeAsync(consumeParams) { billingResult, outToken ->
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
// Handle the success of the consume operation.
LogHelper.log(TAG, "Item Consumed!!!")

Summarizing everything in a single class we will have:

By following these simple, but not at all quick, steps you will have the opportunity to create your own payment client from scratch, without having to jump from link to link to find all the pieces and without having to follow articles that refer to what the console of Google Play, considering that for more than a month they have done a restyle and therefore many items are impossible to find.

Obviously I wanted to concentrate this article on Consumables and non-Consumables but I think it is the minimum necessary to implement payments in your application or in your games. For all that I have not been able to enclose, you will surely find the link that shows you all the useful details on the payment client useful. Making a comparison with the things you are missing from my guide.