In this article, I will show you how to integrate In-App Purchase for Subscription of Google Play in-app purchase Billing Library version 5+ into your Android App. in this tutorial I will follow the google official documentation
What will be required –
- Android Studio to write this code
- Google Play Console Account
- A published App
- Device or Emulator For Test
Step 1
Add the Google Play Billing Library dependency to your app’s build.gradle
file as shown:
dependencies { def billing_version = "5.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Step 2
Initialize a BillingClient with PurchasesUpdatedListener in the onCreate method
billingClient = BillingClient.newBuilder(this) .enablePendingPurchases() .setListener( new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List list) { if(billingResult.getResponseCode()==BillingClient.BillingResponseCode.OK && list !=null) { for (Purchase purchase: list){ verifySubPurchase(purchase); } } } } ).build(); //start the connection after initializing the billing client establishConnection();
Step 3
Establish a connection With Google Play API
void establishConnection() { billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(@NonNull BillingResult billingResult) { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. showProducts(); } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. establishConnection(); } }); }
Step 4
Show the products and make them available to Purchase
@SuppressLint("SetTextI18n") void showProducts() { ImmutableList productList = ImmutableList.of( //Product 1 = index is 0 QueryProductDetailsParams.Product.newBuilder() .setProductId("sub_premium") .setProductType(BillingClient.ProductType.SUBS) .build(), //Product 2 = index is 1 QueryProductDetailsParams.Product.newBuilder() .setProductId("test_id_shar") .setProductType(BillingClient.ProductType.SUBS) .build() ); QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder() .setProductList(productList) .build(); billingClient.queryProductDetailsAsync( params, (billingResult, productDetailsList) -> { // Process the result for (ProductDetails productDetails : productDetailsList) { if (productDetails.getProductId().equals("sub_premium")) { List subDetails = productDetails.getSubscriptionOfferDetails(); assert subDetails != null; Log.d("testOffer",subDetails.get(0).getOfferToken()); txt_price.setText(subDetails.get(0).getPricingPhases().getPricingPhaseList().get(0).getFormattedPrice()+" Per Month"); txt_price.setOnClickListener(view -> { launchPurchaseFlow(productDetails); }); } if (productDetails.getProductId().equals("test_id_shar")) { List subDetails = productDetails.getSubscriptionOfferDetails(); assert subDetails != null; Log.d("testOffer",subDetails.get(1).getOfferToken()); offer_btn.setText(subDetails.get(1).getPricingPhases().getPricingPhaseList().get(0).getFormattedPrice()+" Per Month"); offer_btn.setOnClickListener(view -> { launchPurchaseFlow(productDetails); }); } } } ); }
Step 5
Launch the purchase flow
void launchPurchaseFlow(ProductDetails productDetails) { assert productDetails.getSubscriptionOfferDetails() != null; ImmutableList productDetailsParamsList = ImmutableList.of( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(productDetails.getSubscriptionOfferDetails().get(0).getOfferToken()) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); }
Step 6
Process the purchases and Verify Payment
void verifySubPurchase(Purchase purchases) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams .newBuilder() .setPurchaseToken(purchases.getPurchaseToken()) .build(); billingClient.acknowledgePurchase(acknowledgePurchaseParams, billingResult -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { //user prefs to set premium Toast.makeText(StoreActivity.this, "You are a premium user now", Toast.LENGTH_SHORT).show(); //Setting premium to 1 // 1 - premium // 0 - no premium prefs.setPremium(1); } }); Log.d(TAG, "Purchase Token: " + purchases.getPurchaseToken()); Log.d(TAG, "Purchase Time: " + purchases.getPurchaseTime()); Log.d(TAG, "Purchase OrderID: " + purchases.getOrderId()); }
Step 7
Handling pending transactions
protected void onResume() { super.onResume(); billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS).build(), (billingResult, list) -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { for (Purchase purchase : list) { if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) { verifySubPurchase(purchase); } } } } ); }
Step 8
Check Subscription, run this code while the app starting(the best way will be to use this below code inside your splash screen Activity)
void checkSubscription(){ billingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener((billingResult, list) -> {}).build(); final BillingClient finalBillingClient = billingClient; billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingServiceDisconnected() { } @Override public void onBillingSetupFinished(@NonNull BillingResult billingResult) { if(billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){ finalBillingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.SUBS).build(), (billingResult1, list) -> { if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK){ Log.d("testOffer",list.size() +" size"); if(list.size()>0){ prefs.setPremium(1); // set 1 to activate premium feature int i = 0; for (Purchase purchase: list){ //Here you can manage each product, if you have multiple subscription Log.d("testOffer",purchase.getOriginalJson()); // Get to see the order information Log.d("testOffer", " index" + i); i++; } }else { prefs.setPremium(0); // set 0 to de-activate premium feature } } }); } } }); }
if you want a video tutorial about Integrating the Google Play Billing Library check our YouTube Channel. you will find more awesome tutorials