Google Play Billing Library release notes

This document contains release notes for the Google Play Billing Library.

Version 7.1.1 of the Google Play Billing Library and Kotlin extensions are now available.

Version 7.1.0 of the Google Play Billing Library and Kotlin extensions are now available.

  • Improved thread safety related to connection status and management.
  • Introduced partial changes for testing BillingResult response codes which is fully released in Play Billing Library 7.1.1. To test your integration using this feature, you'll need to upgrade to Play Billing Library 7.1.1. A bug exists that will only impact applications with billing overrides testing enabled and does not affect regular usage. For more information, see Test BillingResult response codes.

Version 7.0.0 of the Google Play Billing Library and Kotlin extensions are now available.

Version 6.2.1 of the Google Play Billing Library and Kotlin extensions are now available.

Version 6.2.0 of the Google Play Billing Library and Kotlin extensions are now available.

Version 6.1.0 of the Google Play Billing Library and Kotlin extensions are now available.

Version 6.0.1 of the Google Play Billing Library and Kotlin extensions are now available.

Update Play Billing Library to be compatible with Android 14.

Version 6.0.0 of the Google Play Billing Library and Kotlin extensions are now available.

  • Added new ReplacementMode enum to replace ProrationMode.

    Please note that ProrationMode is still available for backward compatibility reasons.

  • Removed order ID for PENDING purchases.

    Previously, the order ID would always be created even if the purchase was pending. Starting with version 6.0.0, an order ID will not be created for pending purchases, and for these purchases, the order ID will be populated after the purchase is moved to the PURCHASED state.

  • Removed queryPurchases and launchPriceConfirmationFlow methods.

    The queryPurchases and launchPriceConfirmationFlow methods that have previously been marked as deprecated have now been removed in Play Billing Library 6.0.0. Developers should use queryPurchasesAsync instead of queryPurchases. For launchPriceConfirmationFlow alternatives, see Price changes.

  • Added new network error response code.

    A new network error response code, NETWORK_ERROR, has been added starting with PBL version 6.0.0. This code is returned when an error occurs due to a network connection issue. These network connection errors were previously reported as SERVICE_UNAVAILABLE.

  • Updated SERVICE_UNAVAILABLE and SERVICE_TIMEOUT.

    Starting with PBL version 6.0.0, errors due to timeout in processing will be returned as SERVICE_UNAVAILABLE instead of the current SERVICE_TIMEOUT.

    The behavior does not change in earlier versions of PBL.

  • Removed SERVICE_TIMEOUT.

    Starting with PBL version 6.0.0, SERVICE_TIMEOUT will no longer be returned. Previous versions of PBL will still return this code.

  • Added additional logging.

    The Play Billing Library 6 release includes additional logging, which provides insight into API usage (such as success and failure) and service connection issues. This information will be used to improve the performance of the Play Billing Library and provide better support for errors.

Version 5.2.1 of the Google Play Billing Library and Kotlin extensions are now available.

Update Play Billing Library to be compatible with Android 14.

Version 5.2.0 of the Google Play Billing Library and Kotlin extensions are now available.

Version 5.1.0 of the Google Play Billing Library and Kotlin extensions are now available.

This version contains the following changes.

Version 5.0.0 of the Google Play Billing Library and Kotlin extensions are now available.

This version contains the following changes.

  • Introduced a new model for subscriptions, including new entities that enable you to create multiple offers for a single subscription product. For more information, see the migration guide.
  • Added BillingClient.queryProductDetailsAsync() to replace BillingClient.querySkuDetailsAsync().
  • Added setIsOfferPersonalized() method for EU personalized pricing disclosure requirements. To learn more about how to use this method, see Indicate a personalized price.
  • Removed queryPurchases(), which was previously deprecated and replaced by queryPurchasesAsync introduced in Google Play Billing Library 4.0.0.
  • launchPriceChangeFlow has been deprecated and will be removed in a future release. To learn more about alternatives, see Launch a price change confirmation flow.
  • Removed setVrPurchaseFlow(), which was previously used when instantiating a purchase flow. In previous versions, this method redirected the user to complete the purchase on their Android device. Once you remove this method, users will complete the purchase through the standard purchase flow.

Version 4.1.0 of the Google Play Billing Library and Kotlin extensions are now available.

This version contains the following changes.

Version 4.0.0 of the Google Play Billing Library and Kotlin extensions are now available.

Version 3.0.3 of the Google Play Billing Library, Kotlin extension, and Unity plugin are now available.

  • Fix memory leak when endConnection() is called.
  • Fix issue when the Google Play Billing Library is used by apps which utilize the single task launch mode. A onPurchasesUpdated() callback will be triggered when an app is resumed from the Android launcher and the billing dialog was visible prior to being suspended.
  • Update to Java version 3.0.3 to fix memory leak and resolve issue preventing purchases when an app is resumed from the Android launcher and the billing dialog was visible prior to being suspended.

Version 3.0.2 of the Google Play Billing Library and Kotlin extension are now available.

  • Fixed a bug in the Kotlin extension where the coroutine fails with error "Already resumed".
  • Fixed unresolved references when the Kotlin extension is used with the kotlinx.coroutines library version 1.4+.

Version 3.0.1 of the Google Play Billing Library and Kotlin extension are now available.

  • Fixed a bug where if the app was killed and restored during the billing flow, PurchasesUpdatedListener may not be called with the purchase result.

Version 3.0.0 of the Google Play Billing Library, Kotlin extension, and Unity plugin are now available.

  • Removed rewarded SKU support.
  • Removed the ChildDirected and UnderAgeOfConsent parameters.
  • Removed deprecated developer payload methods.
  • Removed deprecated methods BillingFlowParams.setAccountId() and BillingFlowParams.setDeveloperId().
  • Removed deprecated methods BillingFlowParams.setOldSkus(String oldSku) and BillingFlowParams.addOldSku(String oldSku).
  • Added nullability annotations.

Version 2.2.1 of the Google Play Billing library is now available.

  • Updated the default version of the Java Play Billing library that the Kotlin extension depends on.

Version 2.2.0 of the Google Play Billing provides functionality that helps developers ensure purchases are attributed to the correct user. These changes replace the need to build custom solutions based on developer payload. As part of this update, the developer payload functionality has been deprecated and will be removed in a future release. For more information, including recommended alternatives, see Developer payload.

In addition to the current Java and Kotlin versions of Google Play Billing Library 2, we released a version of the library for use with Unity. Game developers using the Unity in-app purchase API can upgrade now to take advantage of all Google Play Billing Library 2 features and to make the subsequent upgrades to future versions of the Google Play Billing Library easier.

To learn more, see Use Google Play Billing with Unity.

Version 2.1.0 of the Google Play Billing library and the new Kotlin extension are now available. The Play Billing Library Kotlin extension provides idiomatic API alternatives for Kotlin consumption, featuring better null-safety and coroutines. For code examples, see Use the Google Play Billing Library.

This version contains the following changes.

  • In BillingFlowParams, deprecated setOldSku(String oldSku) and replaced with setOldSku(String oldSku, String purchaseToken), to disambiguate when multiple accounts on the device own the same sku.

Version 2.0.3 of the Google Play Billing library is now available.

  • Fixed a bug where querySkuDetailsAsync() would occasionally fail with code DEVELOPER_ERROR instead of returning a successful result.

Version 2.0.2 of the Google Play Billing library is now available. This release contains updates to the reference documentation and does not change library functionality.

Version 2.0.1 of the Google Play Billing library is now available. This version contains the following changes.

  • Fixed a bug where debug messages were being returned as null in some cases.
  • Fixed a potential memory leak issue.

Version 2.0 of the Google Play Billing library is now available. This version contains the following changes.

Google Play supports purchasing products from inside of your app (in-app) or outside of your app (out-of-app). In order for Google Play to ensure a consistent purchase experience regardless of where the user purchases your product, you must acknowledge all purchases received through the Google Play Billing Library as soon as possible after granting entitlement to the user. If you do not acknowledge a purchase within three days, the user automatically receives a refund, and Google Play revokes the purchase. For pending transactions (new in version 2.0), the three-day window starts when the purchase has moved to the PURCHASED state and does not apply while the purchase is in a PENDING state.

For subscriptions, you must acknowledge any purchase that has a new purchase token. This means that all initial purchases, plan changes, and re-signups need to be acknowledged, but you do not need to acknowledge subsequent renewals. To determine if a purchase needs acknowledgment, you can check the acknowledgement field in the purchase.

The Purchase object now includes an isAcknowledged() method that indicates whether a purchase has been acknowledged. In addition, the Google Play Developer API includes acknowledgement boolean values for both Purchases.products and Purchases.subscriptions. Before acknowledging a purchase, be sure to use these methods to determine if the purchase has already been acknowledged.

You can acknowledge a purchase by using one of the following methods:

  • For consumable products, use consumeAsync(), found in the client API.
  • For products that aren't consumed, use acknowledgePurchase(), found in the client API.
  • A new acknowledge() method is also available in the Server API.

The previously-deprecated BillingFlowParams#setSku() method has been removed in this release. Before rendering products in a purchase flow, you must now call BillingClient.querySkuDetailsAsync(), passing the resulting SkuDetails object to BillingFlowParams.Builder.setSkuDetails().

For code examples, see Use the Google Play Billing Library.

Version 2.0 of the Google Play Billing library adds support for developer payload—arbitrary strings that can be attached to purchases. You can attach a developer payload parameter to a purchase, but only when the purchase is acknowledged or consumed. This is unlike developer payload in AIDL, where the payload could be specified when launching the purchase flow. Because purchases can now be initiated from outside of your app, this change ensures that you always have an opportunity to add a payload to purchases.

To access the payload in the new library, Purchase objects now include a getDeveloperPayload() method.

When you offer a discounted SKU, Google Play now returns the original price of the SKU so that you can show users that they are receiving a discount.

SkuDetails contains two new methods for retrieving the original SKU price:

With version 2.0 of the Google Play Billing library, you must support purchases where additional action is required before granting entitlement. For example, a user might choose to purchase your in-app product at a physical store using cash. This means that the transaction is completed outside of your app. In this scenario, you should grant entitlement only after the user has completed the transaction.

To enable pending purchases, call enablePendingPurchases() as part of initializing your app.

Use Purchase.getPurchaseState() to determine whether the purchase state is PURCHASED or PENDING. Note that you should grant entitlement only when the state is PURCHASED. You should check for Purchase status updates by doing the following:

  1. When starting your app, call BillingClient.queryPurchases() to retrieve the list of unconsumed products associated with the user.
  2. Call Purchase.getPurchaseState() on each returned Purchase object.
  3. Implement the onPurchasesUpdated() method to respond to changes to Purchase objects.

In addition, the Google Play Developer API includes a PENDING state for Purchases.products. Pending transactions are not supported for subscriptions.

This release also introduces a new real-time developer notification type, OneTimeProductNotification. This notification type contains a single message whose value is either ONE_TIME_PRODUCT_PURCHASED or ONE_TIME_PRODUCT_CANCELED. This notification type is sent only for purchases associated with delayed forms of payment, such as cash.

When acknowledging pending purchases, be sure to acknowledge only when the purchase state is PURCHASED and not PENDING.

Version 2.0 of the Google Play Billing library contains several API changes to support new features and clarify existing functionality.

consumeAsync() now takes a ConsumeParams object instead of a purchaseToken. ConsumeParams contains the purchaseToken as well as an optional developer payload.

The previous version of consumeAsync() has been removed in this release.

To minimize confusion, queryPurchaseHistoryAsync() now returns a PurchaseHistoryRecord object instead of a Purchase object. The PurchaseHistoryRecord object is the same as a Purchase object, except that it reflects only the values returned by queryPurchaseHistoryAsync() and does not contain the autoRenewing, orderId, and packageName fields. Note that nothing has changed with the returned data—queryPurchaseHistoryAsync() returns the same data as before.

APIs that previously returned a BillingResponse integer value now return a BillingResult object. BillingResult contains the BillingResponse integer as well as a debug string that you can use to diagnose errors. The debug string uses an en-US locale and is not meant to be shown to end users.

Version 1.2.2 of the Google Play Billing library is now available. This version contains the following changes.

  • Fixed a threading issue introduced in v1.2.1. Background calls no longer block the main thread.
  • Although using the main thread is still recommended, you can now instantiate the Google Play Billing Library from a background thread.
  • Instantiation has been fully migrated to the background thread to reduce the chance of causing ANRs.

Version 1.2.1 of the Google Play Billing library is now available. This version contains the following changes.

  • Added public constructors for PurchasesResult and SkuDetailsResult to make testing easier.
  • SkuDetails objects can use a new method, getOriginalJson().
  • All AIDL service calls are now handled by background threads.
  • Null callback listeners are no longer passed into public APIs.

Version 1.2 of the Google Play Billing library is now available. This version contains the following changes.

  • The Google Play Billing Library is now licensed under the Android Software Development Kit License Agreement.
  • Added the launchPriceChangeConfirmationFlow API, which prompts users to review a pending change to a subscription price.
  • Added support for a new proration mode, DEFERRED, when upgrading or downgrading a user's subscription.
  • In the BillingFlowParams class, replaced setSku() with setSkuDetails().
  • Minor bug fixes and code optimizations.

You can now change the price of a subscription in Google Play Console and prompt users to review and accept the new price when they enter your app.

To use this API, create a PriceChangeFlowParams object by using the skuDetails of the subscription product, and then call launchPriceChangeConfirmationFlow(). Implement the PriceChangeConfirmationListener to handle the result when the price change confirmation flow finishes, as shown in the following code snippet:

val priceChangeFlowParams = PriceChangeFlowParams.newBuilder()
    .setSkuDetails(skuDetailsOfThePriceChangedSubscription)
    .build()

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        object : PriceChangeConfirmationListener() {
            override fun onPriceChangeConfirmationResult(responseCode: Int) {
                // Handle the result.
            }
        })
PriceChangeFlowParams priceChangeFlowParams =
        PriceChangeFlowParams.newBuilder()
    .setSkuDetails(skuDetailsOfThePriceChangedSubscription)
    .build();

billingClient.launchPriceChangeConfirmationFlow(activity,
        priceChangeFlowParams,
        new PriceChangeConfirmationListener() {
            @Override
            public void onPriceChangeConfirmationResult(int responseCode) {
                // Handle the result.
            }
        });

The price change confirmation flow displays a dialog containing the new pricing information, asking users to accept the new price. This flow returns a response code of type BillingClient.BillingResponse.

When upgrading or downgrading a user's subscription, you can use a new proration mode, DEFERRED. This mode updates the user's subscription when it next renews. To learn more about how to set this proration mode, see Set proration mode.

In the BillingFlowParams class, the setSku() method has been deprecated. This change serves to optimize the Google Play Billing flow.

When constructing a new instance of BillingFlowParams in your in-app billing client, we recommend that you instead work with the JSON object directly using setSkuDetails(), as shown in the following code snippet:

In the BillingFlowParams Builder class, the setSku() method has been deprecated. Instead, use the setSkuDetails() method, as shown in the following code snippet. The object passed into setSkuDetails() object comes from the querySkuDetailsAsync() method.

private lateinit var mBillingClient: BillingClient
private val mSkuDetailsMap = HashMap<String, SkuDetails>()

private fun querySkuDetails() {
    val skuDetailsParamsBuilder = SkuDetailsParams.newBuilder()
    mBillingClient.querySkuDetailsAsync(skuDetailsParamsBuilder.build()
    ) { responseCode, skuDetailsList ->
        if (responseCode == 0) {
            for (skuDetails in skuDetailsList) {
                mSkuDetailsMap[skuDetails.sku] = skuDetails
            }
        }
    }
}

private fun startPurchase(skuId: String) {
    val billingFlowParams = BillingFlowParams.newBuilder()
    .setSkuDetails(mSkuDetailsMap[skuId])
    .build()
}
private BillingClient mBillingClient;
private Map<String, SkuDetails> mSkuDetailsMap = new HashMap<>();

private void querySkuDetails() {
    SkuDetailsParams.Builder skuDetailsParamsBuilder
            = SkuDetailsParams.newBuilder();
    mBillingClient.querySkuDetailsAsync(skuDetailsParamsBuilder.build(),
            new SkuDetailsResponseListener() {
                @Override
                public void onSkuDetailsResponse(int responseCode,
                        List<SkuDetails> skuDetailsList) {
                    if (responseCode == 0) {
                        for (SkuDetails skuDetails : skuDetailsList) {
                            mSkuDetailsMap.put(skuDetails.getSku(), skuDetails);
                        }
                    }
                }
            });
}

private void startPurchase(String skuId) {
    BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
            .setSkuDetails(mSkuDetailsMap.get(skuId))
            .build();
}

Version 1.1 of the Google Play Billing library is now available. This version contains the following changes.

  • Added support to specify a proration mode in BillingFlowParams when upgrading/downgrading an existing subscription.
  • The replaceSkusProration boolean flag in BillingFlowParams is no longer supported. Use replaceSkusProrationMode instead.
  • launchBillingFlow() now triggers a callback for failed responses.

Version 1.1 of the Google Play Billing library contains the following behavior changes.

A ProrationMode provides further details on the type of proration when upgrading or downgrading a user's subscription.

BillingFlowParams.newBuilder()
    .setSku(skuId)
    .setType(billingType)
    .setOldSku(oldSku)
    .setReplaceSkusProrationMode(replaceSkusProrationMode)
    .build()

BillingFlowParams.newBuilder()
    .setSku(skuId)
    .setType(billingType)
    .setOldSku(oldSku)
    .setReplaceSkusProrationMode(replaceSkusProrationMode)
    .build();

Currently, Google Play supports following proration modes:

IMMEDIATE_WITH_TIME_PRORATION Replacement takes effect immediately, and the new expiration time will be prorated and credited or charged to the user. This is the current default behavior.
IMMEDIATE_AND_CHARGE_PRORATED_PRICE Replacement takes effect immediately, and the billing cycle remains the same. The price for the remaining period will be charged.

Note: This option is only available for subscription upgrade.

IMMEDIATE_WITHOUT_PRORATION Replacement takes effect immediately, and the new price will be charged on next recurrence time. The billing cycle stays the same.

Developers used to be able to set a boolean flag to charge a prorated amount for a subscription upgrade request. Given that we are supporting ProrationMode, which contains more detailed proration instruction, this boolean flag is no longer supported.

The Billing Library will always trigger the PurhcasesUpdatedListener callback and return a BillingResponse asynchronously. The synchronous return value of BillingResponse is kept as well.

  • Properly exits early in async methods when service is disconnected.
  • Builder param objects no longer mutates built objects.
  • Issue 68087141: launchBillingFlow() now trigger callback for failed responses.

Version 1.0 of the Google Play Billing library is now available. This version contains the following changes.

  • Embedded billing permission inside library’s manifest. It's not necessary to add the com.android.vending.BILLING permission inside Android manifest anymore.
  • New builder added to BillingClient.Builder class.
  • Introduced builder pattern for SkuDetailsParams class to be used on methods to query SKUs.
  • Several API methods were updated for consistency (the same return argument names and order).

Version 1.0 of the Google Play Billing library contains the following behavior changes.

BillingClient.Builder is now initialized via the newBuilder pattern:

billingClient = BillingClient.newBuilder(context).setListener(this).build()
billingClient = BillingClient.newBuilder(context).setListener(this).build();

To initiate the billing flow for a purchase or subscription, the launchBillingFlow() method receives a BillingFlowParams instance initialized with parameters specific to the request:

BillingFlowParams.newBuilder().setSku(skuId)
        .setType(billingType)
        .setOldSku(oldSku)
        .build()

// Then, use the BillingFlowParams to start the purchase flow
val responseCode = billingClient.launchBillingFlow(builder.build())
BillingFlowParams.newBuilder().setSku(skuId)
                              .setType(billingType)
                              .setOldSku(oldSku)
                              .build();

// Then, use the BillingFlowParams to start the purchase flow
int responseCode = billingClient.launchBillingFlow(builder.build());

Arguments for queryPurchaseHistoryAsync() and querySkuDetailsAsync() methods were wrapped into a Builder pattern:

val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList)
        .setType(itemType)
billingClient.querySkuDetailsAsync(params.build(), object : SkuDetailsResponseListener() {
    ...
})
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList)
        .setType(itemType);
billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {...})

The result is now returned via result code and a list of SkuDetails objects instead of previous wrapper class for your convenience and to be consistent across our API:

fun onSkuDetailsResponse(@BillingResponse responseCode: Int, skuDetailsList: List<SkuDetails>)
public void onSkuDetailsResponse(@BillingResponse int responseCode, List<SkuDetails> skuDetailsList)

The order of arguments for onConsumeResponse from the ConsumeResponseListener interface has changed to be consistent across our API:

fun onConsumeResponse(@BillingResponse responseCode: Int, outToken: String)
public void onConsumeResponse(@BillingResponse int responseCode, String outToken)

PurchaseResult has been unwraped to be consistent across our API:

fun onPurchaseHistoryResponse(@BillingResponse responseCode: Int, purchasesList: List<Purchase>)
void onPurchaseHistoryResponse(@BillingResponse int responseCode, List<Purchase> purchasesList)

Developer preview launched, aimed to simplify the development process when it comes to billing, allowing developers to focus their efforts on implementing logic specific to the Android app, such as application architecture and navigation structure.

The library includes several convenient classes and features for you to use when integrating your Android apps with the Google Play Billing API. The library also provides an abstraction layer on top of the Android Interface Definition Language (AIDL) service, making it easier for developers to define the interface between the app and the Google Play Billing API.