Consumable Item In-App Purchases: https://github.com/wdtheprovider/in-app-purchase
In this repository i'm going to show you how to integrate In-App Purchases of Google Play Billing version 5+ in 8 steps. I follow the officailly google docs, i'm not using any third-party library
Pre-requisite
- Google Play Console Account
- Published App on Play Store
- Tester Device with GMS
YouTube Video: Part-1 | Intro Demo: https://youtu.be/nQrsVB7quKw
YouTube Video: Part-2 | Configure Testing Device: https://youtu.be/j6wWVMj-fi8
YouTube Video: Part-3 | Integrating The Methods to purchase the products: https://www.youtube.com/watch?v=7cf8yHdXMdA
Configure Your Testing device by adding the gmail account to internal testing testers
and License testing (Watch the YouTube video for clarity: https://youtu.be/j6wWVMj-fi8 )
Setup the in-app purchase product in Google Play Console account
i have already created mine which are
Product IDs:
productIds = new ArrayList<>();
coins = new ArrayList<>();
productIds.add("10_coins_id");
coins.add(10);
productIds.add("20_coins_id");
coins.add(20);
productIds.add("50_coins_id");
coins.add(50);
The following methods (These are the methods you need for the IAP System to work, you can copy and paste)
void establishConnection(){}
void showProducts(){}
void launchPurchaseFlow(){}
void verifySubPayment(Purchase purchases){}
void checkSubscription(){}
void giveUserCoins (){}
Step 1: Add the Google Play Billing Library dependency
Step 2: Initialize a BillingClient with PurchasesUpdatedListener
Step 3: Establish a connection to Google Play
Step 4: Show products available to buy
Step 5: Launch the purchase flow
Step 6: Processing purchases / Verify Payment
Step 7: Handling pending transactions
Learn More: https://developer.android.com/google/play/billing/integrate
//Add the Google Play Billing Library dependency to your app's build.gradle file as shown:
dependencies {
def billing_version = "6.0.0"
implementation "com.android.billingclient:billing:$billing_version"
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
implementation 'com.google.guava:guava:24.1-jre'
}
//And Open Manifest File and add this permission
<uses-permission android:name="com.android.vending.BILLING" />
//Initialize a BillingClient with PurchasesUpdatedListener onCreate method
billingClient = BillingClient.newBuilder(this)
.enablePendingPurchases()
.setListener(
new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> 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();
void connectGooglePlayBilling() {
billingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingServiceDisconnected() {
connectGooglePlayBilling();
}
@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
showProducts();
}
}
});
}
@SuppressLint("SetTextI18n")
void showProducts() {
ImmutableList<QueryProductDetailsParams.Product> productList = ImmutableList.of(
//Product 1
QueryProductDetailsParams.Product.newBuilder()
.setProductId("coins_id")
.setProductType(BillingClient.ProductType.INAPP)
.build()
);
QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
.setProductList(productList)
.build();
billingClient.queryProductDetailsAsync(params, (billingResult, list) -> {
productDetailsList.clear();
handler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "posted delayed");
loadProducts.setVisibility(View.INVISIBLE); //
productDetailsList.addAll(list);
Log.d(TAG, productDetailsList.size() + " number of products");
adapter = new BuyCoinsAdapter(getApplicationContext(), productDetailsList, BuyCoinActivity.this);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(BuyCoinActivity.this, LinearLayoutManager.VERTICAL, false));
recyclerView.setAdapter(adapter);
}
}, 2000);
});
}
void launchPurchaseFlow(ProductDetails productDetails) {
ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList =
ImmutableList.of(
BillingFlowParams.ProductDetailsParams.newBuilder()
.setProductDetails(productDetails)
.build()
);
BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
.setProductDetailsParamsList(productDetailsParamsList)
.build();
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
}
void verifyPurchase(Purchase purchase) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = (billingResult, s) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
giveUserCoins(purchase);
}
};
billingClient.consumeAsync(consumeParams, listener);
}
protected void onResume() {
super.onResume();
billingClient.queryPurchasesAsync(
QueryPurchasesParams.newBuilder().setProductType(BillingClient.ProductType.INAPP).build(),
(billingResult, list) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
for (Purchase purchase : list) {
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED && !purchase.isAcknowledged()) {
verifyPurchase(purchase);
}
}
}
}
);
}
@SuppressLint("SetTextI18n")
void giveUserCoins(Purchase purchase) {
Log.d("TestINAPP", purchase.getProducts().get(0));
Log.d("TestINAPP", purchase.getQuantity() + " Quantity");
for(int i=0;i<productIds.size();i++){
if(purchase.getProducts().get(0).equals(productIds.get(i))){
Log.d(TAG,"Balance "+prefs.getInt("coins",0)+ " Coins");
Log.d(TAG,"Allocating "+coins.get(i) + " Coins");
//set coins
prefs.setInt("coins",coins.get(i) + prefs.getInt("coins",0));
Log.d(TAG,"New Balance "+prefs.getInt("coins",0)+ " Coins");
//Update UI
txt_coins.setText(prefs.getInt("coins",0)+"");
}
}
}
Buy recyclerviewer adapter: https://dingi.icu/store/