Setup Google Play developer account
Google Play console use we can manage our products with Google Play Billing.
To sell our products with Google Play we need GooglePaymentcenter profile account
Then we need to link this account with Google Play developer account.
You can check how to Link GooglePlay developer account
Enable Google Play Billing
Once we are ready with developer account we must publish our app with including Google Play Billing dependencies.
This step is used to enable Google Play Billing features in the Google Play Console
Add Google Play Billing dependencies
add below dependencies in app levlel build.gradle file
dependencies { implementation 'com.android.billingclient:billing:$billing_version'//Android |
After adding this, just create a bundle/apk and publish it in Googleplay Console in Alpha/beta/Testing track mode
Create Products
We can add our products for two ways
After adding product now come to application and add your logic to show products and display subscription plans
Create BillingClient object
mBillingClient = BillingClient.newBuilder(this).setListener(new PurchasesUpdatedListener() {
|
Start Billing connection to get data
mBillingClient.startConnection(new BillingClientStateListener() {
} @Override |
Get all Subscription/Products list from Merchant account and display it.
To fetch products we need to request with its product ids
final List<String> skuList = new ArrayList<>(); skuList.add("weekly"); // SKU Id } |
Launch Billing FlowSubscrib Plan
To subscribe specific plan/Products we need to launch Billing flow
BillingFlowParams.Builder builder = BillingFlowParams.newBuilder() |
We can get status of subscribed product under PurchasesUpdatedListener(), there we need to save access Key of the products/subscription plan. This key we need to save at your app level/server side
Check Subscription Status
If we subscribe any product/subscription, to verify it status we need it access Key.
To check status we need to use acknowledgePurchase() query
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener=new AcknowledgePurchaseResponseListener() { Log.v("Onresposne","Onresposne purchased "+billingResult.getResponseCode()); |
Example Code
Activity.java
package com.rrtutors.inapppurchase;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
public class MySubScription extends AppCompatActivity {
Button btn_sub;
TextView txt_des;
String[]subTypeList;
Dialog alertDialog1;
BillingClient mBillingClient;
Activity _this;
SharedPreferences sh;
int pos=0;
List<SkuDetails>skuListData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sub_scription);
btn_sub=findViewById(R.id.btn_sub);
txt_des=findViewById(R.id.txt_des);
btn_sub.setEnabled(false);
openConnection();
_this=this;
sh=getSharedPreferences("mysub",MODE_PRIVATE);
btn_sub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(subTypeList==null||subTypeList.length<=0)
{
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(MySubScription.this);
builder.setTitle("Select Your Choice");
builder.setSingleChoiceItems(subTypeList, -1, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
pos=item;
}
});
builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialog1.dismiss();
if(skuListData!=null&&skuListData.size()>pos)
{
BillingFlowParams.Builder builder = BillingFlowParams.newBuilder()
.setSkuDetails(skuListData.get(pos));
mBillingClient.launchBillingFlow(_this, builder.build());
}
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialog1.dismiss();
}
});
alertDialog1 = builder.create();
alertDialog1.show();
}
});
}
private void openConnection()
{
mBillingClient = BillingClient.newBuilder(this).setListener(new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> purchases) {
Log.v("dfdsf","gggggg "+billingResult.getResponseCode());
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK
&& purchases != null) {
for (Purchase purchase : purchases) {
sh.edit().putString("key",purchase.getPurchaseToken()).commit();
}
} else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
// Handle an error caused by a user cancelling the purchase flow.
} else {
// Handle any other error codes.
}
}
}).enablePendingPurchases()
.build();
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResponseCode) {
Log.v("ResposneCode","ResposneCode "+billingResponseCode.getResponseCode());
if (billingResponseCode.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// String key=getSharedPreferences("mysub",MODE_PRIVATE).getString("key","");
// Log.v("Onresposne","Onresposne purchased key "+key);
btn_sub.setEnabled(true);
checkStatus();
showList();
}
}
@Override
public void onBillingServiceDisconnected() {
// Try to restart the connection on the next request to
// Google Play by calling the startConnection() method.
}
});
}
private void showList()
{
/**
* To purchase an Subscription
*/
final List<String> skuList = new ArrayList<>();
skuList.add("weekly"); // SKU Id
skuList.add("monthly"); // SKU Id
skuList.add("3months"); // SKU Id
skuList.add("6months"); // SKU Id
SkuDetailsParams params = SkuDetailsParams.newBuilder()
.setSkusList(skuList)
.setType(BillingClient.SkuType.SUBS)
.build();
mBillingClient.querySkuDetailsAsync(params,
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList)
{
Log.v("ResposneCode","ResposneCode11 "+billingResult.getResponseCode());
Log.v("ResposneCode","ResposneCode12 "+skuDetailsList);
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
Log.v("ResposneCode","ResposneCode13 "+skuDetailsList.size());
Product product;
skuListData=skuDetailsList;
subTypeList=new String[skuListData.size()];
for (int k=0;k<skuDetailsList.size();k++)
subTypeList[k]=(skuDetailsList.get(k).getTitle()+"\n Price "+skuDetailsList.get(k).getPrice()+"\n").replaceAll("(InAppSubscription)"," Sub ");
}
}
});
}
private void checkStatus()
{
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener=new AcknowledgePurchaseResponseListener() {
@Override
public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
Log.v("Onresposne","Onresposne purchased "+billingResult.getResponseCode());
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
btn_sub.setVisibility(View.GONE);
txt_des.setText("You already Subscribed, You can access all Content.");
}else{
btn_sub.setVisibility(View.VISIBLE);
txt_des.setText("To Access all content please subscribe.");
}
}
};
String key=getSharedPreferences("mysub",MODE_PRIVATE).getString("key","");
if(key.isEmpty())
{
return;
}
AcknowledgePurchaseParams acknowledgePurchaseParams =
AcknowledgePurchaseParams.newBuilder()
.setPurchaseToken(key)
.build();
mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
}
}
|
xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:background="@color/colorPrimary"
tools:context="com.rrtutors.inapppurchase.MySubScription">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_margin="10dp"
android:layout_gravity="center"
app:cardCornerRadius="10dp"
app:cardElevation="10dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_margin="10dp"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txt_des"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:text="To Access all content please subscribe"
/>
<Button
android:id="@+id/btn_sub"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:text="Subscribe"
android:background="#07DB73"
android:layout_margin="10dp"
android:textColor="#FFF"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
|
Output
Article Contributed By :
|
|
|
|
3684 Views |