However, I recently had a chance to try out the new Play Billing Library from Google and it’s a dream come true for in-app billing. In this post, I want to take a look at the library, what we can do with it and how we can achieve this functionality.
The Play Billing Library gives us the ability to easily implement in-app purchases and subscriptions in our apps, with reduced boilerplate and code required when compared to previous approaches. This billing library allows us to perform a collection of different operations when it comes to in-app billing:
Now if you’re already using the in-app billing library from Google, you may be thinking — why should I be considering using the play billing library?
- If you don’t currently have any in-app billing setup within your application, then I feel like it would make sense to go ahead and use what is the most current way of doing so.
- If you already have in-app billing implemented in your app, then it may not make sense to switch over to the play billing library right away. The documentation does not state the library as a replacement, but more as an easier way of implementing in-app billing.
- However, the library does allow you to reduce the amount of code required to implement in-app billing. This not only makes the in-app billing flow easy to implement, but it will be tidier to implement and therefore easier to maintain
- On a final note, because it is newer and easier to implement I personally found that for developers who may not have any experience with in-app billing, the Play Billing Library makes the whole implementation process a lot more enjoyable. So for future developers joining the team, it may be a nicer choice to use the Play Billing Library.
To get going with the Play Billing library you need to begin by adding the following dependency to your application-level build.gradle file:
compile 'com.android.billingclient:billing:1.0'
Note: Be sure to check the version number when adding the dependancy as a newer version may be available at the time of you reading this.
Now we have the Play Billing API available in our project, we need to construct an instance of the BillingClient class. This can be instantiated by using the static newBuilder() method, passing in the reference to the activity which we are associating our Billing Client with. Finally, we can use the setListener() method to pass in a reference to our PurchasesUpdatedListener instance which is used to receive callbacks when the purchases for the current user are changed.
https://gist.github.com/hitherejoe/74c405eb396bf384a0873dfc8408842e
Now that we have a reference to the Billing Client instance we can go ahead and kick off the connection to the in-app billing API. Because this request is asynchronous, we pass in an instance of a BillingClientStateListener so that we can receive events based on the status of our API connection.
https://gist.github.com/hitherejoe/b476ec9482be9415733676131dfe2fe7
When you connect to the billing service and the connection is successful the onBillingSetupFinished() callback will receive an event — this is the point at which you will be able to interact with the billing service and query purchases, make purchases and so on. However, if the connection fails then the onBillingServiceDisconnected() will be triggered and you will need to handle the retrying of the connection yourself.
When interacting with the Play Billing Library, most requests will return a response code in the form of a BillingResponse. The value of this can be one of many values, so lets take a look at the possibilities here.
Whenever we interact with the Play Billing API most of the time we are returned a response code that depicts the result of the operation that we carried out. This will be one of 11 response codes, these are useful for handling the error within your application in the most beneficial way possible for the user.
- BILLING_UNAVAILABLE — Returned when the version for the Billing API is not supported for the requested type
- DEVELOPER_ERROR — Returned when incorrect arguments have been sent to the Billing API
- ERROR — General error response returned when an error occurs during the API action being executed
- FEATURE_NOT_SUPPORTED — Returned when the requested action is not supported by play services on the current device
- ITEM_ALREADY_OWNED — Returned when the user attempts to purchases an item that they already own
- ITEM_NOT_OWNED — Returned when the user attempts to consume an item that they do not currently own
- ITEM_UNAVAILABLE — Returned when the user attempts to purchases a product that is not available for purchase
- OK — Returned when the current request is successful
- SERVICE_DISCONNECTED — Returned when the play service is not connected at the point of the request
- SERVICE_UNAVAILABLE — Returned when an error occurs in relation to the devices network connectivity
- USER_CANCELED — Returned when the user cancels the request that is currently taking place
In our application, we may want to display a list of items which are available for purchase within our application. Thankfully, the Play Billing library provides the ability for us to retrieve a list of details for the items which are available for purchase.
To do this we need to send a list of the SKUs which we wanted to retrieve the details for. We begin by using the SkuDetailsParams class to construct a new instance and setting the desired SKUs to our SKU list. At this point we also need to set the type of items we wish to be returned by the query — this will be either in-app purchase items or subscriptions. In the case of this query we’re after in-app purchases, so we’re going to use the INAPP SkuType.
https://gist.github.com/hitherejoe/a8b693d42db9788a5b4415d2763576a6
Now that we have our params setup, we just need to call the querySkuDetailsAsync() method, passing in our parameters:
https://gist.github.com/hitherejoe/fc7dd71703578ecf08b9d1aac9131b9f
Upon a successful request, we will receive back a list of SkuDetails instances. If the request fails, we will be able to handle the result accordingly using the returned responseCode.
On the other hand, we may want to also provide a list of available subscriptions to the user. Again, this is something that the play billing library can do for us out of the box. In fact, it’s done in pretty much the same way that we retrieve a list of available items for purchase — except this time instead of using the INAPP SkuType as our SKU type we use the SUBS value. This tells the Play Billing Library that we want to retrieve a list of subscription details for the provided SKU IDs that we have provided.
https://gist.github.com/hitherejoe/9817d53a32cb3a85fdd5dc8671195a86
Now that we have our params setup, we just need to call the querySkuDetailsAsync() method, passing in our parameters:
https://gist.github.com/hitherejoe/fc7dd71703578ecf08b9d1aac9131b9f
Upon a successful request, we will receive back a list of SkuDetails instances. If the request fails, we will be able to handle the result accordingly using the returned responseCode.
We can query our users’ current purchases using the queryPurchaseHistoryAsync() method. There is also a queryPurchases() method available, but this uses a cached result — so if you need to check for the most up-to-date status of a users’ purchase then the first method would be more desirable to use.
https://gist.github.com/hitherejoe/a120602131d633c738a9d8e912a14872
As you can see, when calling this method we just need to pass in an instance of the SkuType that we wish to receive results for — which in this case is the INAPP type, along with a PurchaseHistoryResponseListener. This listener will receive events for when the query is complete, allowing us to handle the result in our app accordingly depending on the state of the responseCode received.
We can query our users’ current subscriptions using the queryPurchaseHistoryAsync() method. There is also a queryPurchases() method available, but this uses a cached result — so if you need to check for the most up-to-date status of a users’ purchase then the first method would be more desirable to use.
https://gist.github.com/hitherejoe/bd14e5080a01f62091fddafb746f41ee
As you can see, when calling this method we just need to pass in an instance of the SkuType that we wish to receive results for — which in this case is the SUBS type, along with a PurchaseHistoryResponseListener. This listener will receive events for when the query is complete, allowing us to handle the result in our app accordingly depending on the state of the responseCode received.
Upon a successful request we will receive back a list of SkuDetails instances. If the request fails, we will be able to handle the result accordingly using the returned responseCode.
The Play Billing Library provides us with the functionality to consume any items which have previously purchased— this can be useful for tangible things such as power-ups in games or timed unlocking of features. This can be done by using the consumeAsync() method and as parameters, this method takes the purchase token (which would have been received when the item was purchased) and an instance of the ConsumeResponseListener class as a callback for the result of the consumption.
https://gist.github.com/hitherejoe/eb7c279ecff6ee83f2ab0173f2c930e3
When an event is received within the listener, the returned response code can be used to handle the result within your app accordingly.
When we set up our billing client, we passed in a listener instance to listen for changes to purchases:
https://gist.github.com/hitherejoe/74c405eb396bf384a0873dfc8408842e
This listener will be called whenever there has been a change to the users purchases occurring from a purchase operation performed using the library.
https://gist.github.com/hitherejoe/6bdb4679b2468302379b92dff9978af4
When an event is received we will receive a response code which depicts whether or not the purchase was successful, as well as a list of Purchase instances for the purchases that have been made.
When it comes to purchasing a subscription, we can use the Play Billing Library to execute this request. To do so, we need to begin by constructing an instance of the BillingFlowParams class to provide the required parameters for the purchase flow, we can build an instance of this using its newBuilder() method.
From here we need to set the SKU id for the item which we wish to purchase by using the setSku() method, followed by setting the type for the purchase taking place by using the setType() method. For the purchasing of a subscription, this is going to be the SUBS SkuType.
https://gist.github.com/hitherejoe/5d024c824c233fba1925e04d56f441f3
Now that we have these parameters ready, we can go ahead and use the launchBillingFlow() method to kick off the purchase flow. This method takes a reference to the activity you are launching the flow from (as this is required for the callbacks of the request) followed by the parameters that we previously constructed.
https://gist.github.com/hitherejoe/3f5686ea50b29cedc9d107b0f898eff9
When the user finishes (or cancels) the billing flow, then the response is returned in the form of a BillingResponse value so that you can handle the situation accordingly.
When it comes to purchasing an item, we can use the Play Billing Library to execute this request. To do so, we need to begin by constructing an instance of the BillingFlowParams class to provide the required parameters for the purchase flow, we can build an instance of this using its newBuilder() method.
From here we need to set the SKU id for the item which we wish to purchase by using the setSku() method, followed by setting the type for the purchase taking place by using the setType() method. For the purchasing of an item, this is going to be the INAPP SkuType.
https://gist.github.com/hitherejoe/25dad3ebd5edc88f22093f93321bdb8d
Now that we have these parameters ready, we can go ahead and use the launchBillingFlow() method to kick off the purchase flow. This method takes a reference to the activity you are launching the flow from (as this is required for the callbacks of the request) followed by the parameters that we previously constructed.
https://gist.github.com/hitherejoe/3f5686ea50b29cedc9d107b0f898eff9
When the user finishes (or cancels) the billing flow, then the response is returned in the form of a BillingResponse value so that you can handle the situation accordingly.
I hope from this post you’ve been able to see the benefits which the Play Billing Library can bring when it comes to implementing in-app billing into your application. If you’re already using the library or plan on using it, I’d love to hear of any opinions or issues you may have!