In-app Billing Version 3 (IAP V3) easy to integrate In-app Purchase in an app.we can add our Products and Subscription Plans and offer the user to buy them and get the profit of that Service.
I am not able to Implement In-App Purchase or In-App Billing Functionality in my Android App.
Please elaborate In-App Purchase Tutorial with step by step.
I am using Android Studio for Developing Android App, What I have to import or add in SDK?
How to Implement In-App Billing Version3 in Android Application?
I have to implement in-app purchases of the TrivialDrive sample app from google samples but I have got no proper details and not import this project into my Android Studio.
- 5 years ago
To implement In-App Billing subscription you can use Lib which helps Android Developers to implement In-app purchase easy
Follow me :
What needs to implement in-App Billing?
- You should have Google Play Console
- You should have copy License KEY from Google Play Store Console
- Develop your app by copy below code.
- Subscription/ Product ID by clicking on In-app products -> SUBSCRIPTIONS / MANAGED PRODUCTS -> Create managed product
- You can see working subcription /Products working state only when your App live. (WAIT FOR APP LIVE)
Add dependency in your gradle file
compile 'com.anjlab.android.iab.v3:library:1.0.44'
InappBilling_Class.java
import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.util.Log; import android.widget.Toast; import com.anjlab.android.iab.v3.BillingProcessor; import com.anjlab.android.iab.v3.SkuDetails; import com.anjlab.android.iab.v3.TransactionDetails; import com.techximum.funbook.R; import com.techximum.funbook.validationPack.CustomeDialogClass; /** * Created by Hemant on 3/13/2018. */ public class InappBilling_Class { Activity activity; private BillingProcessor bp; Dialog progressDialog; String SUBSCRIPTION_ID = ""; String LICENSE_KEY = ""; int i = 0; // put your Google merchant id here (as stated in public profile of your Payments Merchant Center) // if filled library will provide protection against Freedom alike Play Market simulators private static final String MERCHANT_ID = "10001";// PUT YOUR MERCHANT KEY HERE; // SAMPLE APP CONSTANTS private static final String LOG_TAG = "fSUBSCRIPTION_TAG"; public InappBilling_Class(Activity in_activity, BillingProcessor bpro) { this.activity = in_activity; this.bp = bpro; LICENSE_KEY = activity.getString(R.string.SUBSCRIPTION_LICENSE_KEY); } public BillingProcessor initMethod() { progressDialog = new Dialog(activity); CustomeDialogClass.show(progressDialog, "Initializing...", true); if (!BillingProcessor.isIabServiceAvailable(activity)) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); CustomeDialogClass.oKDialogBox(builder, "ERROR!", "In-app billing service is unavailable, please upgrade Android Market/Play to version >= 3.9.16", R.drawable.ic_wait_crash, false, true); } bp = new BillingProcessor(activity, LICENSE_KEY, MERCHANT_ID, new BillingProcessor.IBillingHandler() { @Override public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) { //showToast("onProductPurchased: " + productId); System.out.println(productId+" ***TRANSACTION DETAILS*** " + details); updateTextViews(1); } @Override public void onBillingError(int errorCode, @Nullable Throwable error) { showToast("onBillingError: " + Integer.toString(errorCode)+" ___ "+error); } @Override public void onBillingInitialized() { // showToast("onBillingInitialized"); progressDialog.dismiss(); updateTextViews(2); } @Override public void onPurchaseHistoryRestored() { showToast("onPurchaseHistoryRestored"); for (String sku : bp.listOwnedProducts()) Log.d(LOG_TAG, "Owned Managed Product: " + sku); for (String sku : bp.listOwnedSubscriptions()) { Log.d(LOG_TAG, "Owned Subscription: " + sku); SUBSCRIPTION_ID = sku; showSunscriptionDetails(); } } }); return bp; } public boolean subscribemethod(String SKU_CODE) { SUBSCRIPTION_ID=SKU_CODE; return bp.subscribe(activity, SKU_CODE); } public void updateTextViews(int ia) { if(!SUBSCRIPTION_ID.isEmpty()) { i++; // TextView protext = (TextView)findViewById(R.id.productIdTextView); // protext.setText(String.format("%s is%s purchased", PRODUCT_ID, bp.isPurchased(PRODUCT_ID) ? "" : " not")); // TextView subtext = (TextView)findViewById(R.id.subscriptionIdTextView); // subtext.setText(String.format("%s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not")); showToast(String.format(" %s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not") + " | " + SUBSCRIPTION_ID); if (bp.isSubscribed(SUBSCRIPTION_ID)) { showSunscriptionDetails(); } else { showToast(String.format("is not subscribed") + " | " + SUBSCRIPTION_ID); } } } private void showToast(String message) { Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); } void showSunscriptionDetails() { SkuDetails subs = bp.getSubscriptionListingDetails(SUBSCRIPTION_ID); System.out.println("***__SUBSCRIPTION__*** " + subs); //showToast(subs != null ? subs.toString() : "Failed to load subscription details"); AlertDialog.Builder builderDetails = new AlertDialog.Builder(activity); builderDetails.setPositiveButton("Okay!", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { activity.onBackPressed(); } }); CustomeDialogClass.oKDialogBox(builderDetails, "Subscribed Plan : "+subs.title, subs.description + "\nPrice : "+subs.priceText+ "\nSubscription Period : "+subs.introductoryPriceCycles, R.drawable.ic_wallet, false, false); } }
Now come on your SubscriptionActivity.java
public class SubscriptionActivity extends Activity { InappBilling_Class inapp; private BillingProcessor bp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_subscription); ... inapp = new InappBilling_Class(SubscriptionActivity.this, bp); bp = inapp.initMethod(); .... } @Override protected void onResume() { super.onResume(); inapp.updateTextViews(3); } @Override public void onDestroy() { if (bp != null) bp.release(); super.onDestroy(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (!bp.handleActivityResult(requestCode, resultCode, data)) super.onActivityResult(requestCode, resultCode, data); System.out.println("**********" + data.getData() + "**********"); }}
Enjoy your subscription/ Products showing In-App.
- 5 years ago
To implement In-App Billing subscription you can use Lib which helps Android Developers to implement In-app purchase easy
Follow me :
What needs to implement in-App Billing?
- You should have Google Play Console
- You should have copy License KEY from Google Play Store Console
- Develop your app by copy below code.
- Subscription/ Product ID by clicking on In-app products -> SUBSCRIPTIONS / MANAGED PRODUCTS -> Create managed product
- You can see working subcription /Products working state only when your App live. (WAIT FOR APP LIVE)
Add dependency in your gradle file
compile 'com.anjlab.android.iab.v3:library:1.0.44'
InappBilling_Class.java
import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.util.Log; import android.widget.Toast; import com.anjlab.android.iab.v3.BillingProcessor; import com.anjlab.android.iab.v3.SkuDetails; import com.anjlab.android.iab.v3.TransactionDetails; import com.techximum.funbook.R; import com.techximum.funbook.validationPack.CustomeDialogClass; /** * Created by Hemant on 3/13/2018. */ public class InappBilling_Class { Activity activity; private BillingProcessor bp; Dialog progressDialog; String SUBSCRIPTION_ID = ""; String LICENSE_KEY = ""; int i = 0; // put your Google merchant id here (as stated in public profile of your Payments Merchant Center) // if filled library will provide protection against Freedom alike Play Market simulators private static final String MERCHANT_ID = "10001";// PUT YOUR MERCHANT KEY HERE; // SAMPLE APP CONSTANTS private static final String LOG_TAG = "fSUBSCRIPTION_TAG"; public InappBilling_Class(Activity in_activity, BillingProcessor bpro) { this.activity = in_activity; this.bp = bpro; LICENSE_KEY = activity.getString(R.string.SUBSCRIPTION_LICENSE_KEY); } public BillingProcessor initMethod() { progressDialog = new Dialog(activity); CustomeDialogClass.show(progressDialog, "Initializing...", true); if (!BillingProcessor.isIabServiceAvailable(activity)) { AlertDialog.Builder builder = new AlertDialog.Builder(activity); CustomeDialogClass.oKDialogBox(builder, "ERROR!", "In-app billing service is unavailable, please upgrade Android Market/Play to version >= 3.9.16", R.drawable.ic_wait_crash, false, true); } bp = new BillingProcessor(activity, LICENSE_KEY, MERCHANT_ID, new BillingProcessor.IBillingHandler() { @Override public void onProductPurchased(@NonNull String productId, @Nullable TransactionDetails details) { //showToast("onProductPurchased: " + productId); System.out.println(productId+" ***TRANSACTION DETAILS*** " + details); updateTextViews(1); } @Override public void onBillingError(int errorCode, @Nullable Throwable error) { showToast("onBillingError: " + Integer.toString(errorCode)+" ___ "+error); } @Override public void onBillingInitialized() { // showToast("onBillingInitialized"); progressDialog.dismiss(); updateTextViews(2); } @Override public void onPurchaseHistoryRestored() { showToast("onPurchaseHistoryRestored"); for (String sku : bp.listOwnedProducts()) Log.d(LOG_TAG, "Owned Managed Product: " + sku); for (String sku : bp.listOwnedSubscriptions()) { Log.d(LOG_TAG, "Owned Subscription: " + sku); SUBSCRIPTION_ID = sku; showSunscriptionDetails(); } } }); return bp; } public boolean subscribemethod(String SKU_CODE) { SUBSCRIPTION_ID=SKU_CODE; return bp.subscribe(activity, SKU_CODE); } public void updateTextViews(int ia) { if(!SUBSCRIPTION_ID.isEmpty()) { i++; // TextView protext = (TextView)findViewById(R.id.productIdTextView); // protext.setText(String.format("%s is%s purchased", PRODUCT_ID, bp.isPurchased(PRODUCT_ID) ? "" : " not")); // TextView subtext = (TextView)findViewById(R.id.subscriptionIdTextView); // subtext.setText(String.format("%s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not")); showToast(String.format(" %s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not") + " | " + SUBSCRIPTION_ID); if (bp.isSubscribed(SUBSCRIPTION_ID)) { showSunscriptionDetails(); } else { showToast(String.format("is not subscribed") + " | " + SUBSCRIPTION_ID); } } } private void showToast(String message) { Toast.makeText(activity, message, Toast.LENGTH_LONG).show(); } void showSunscriptionDetails() { SkuDetails subs = bp.getSubscriptionListingDetails(SUBSCRIPTION_ID); System.out.println("***__SUBSCRIPTION__*** " + subs); //showToast(subs != null ? subs.toString() : "Failed to load subscription details"); AlertDialog.Builder builderDetails = new AlertDialog.Builder(activity); builderDetails.setPositiveButton("Okay!", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { activity.onBackPressed(); } }); CustomeDialogClass.oKDialogBox(builderDetails, "Subscribed Plan : "+subs.title, subs.description + "\nPrice : "+subs.priceText+ "\nSubscription Period : "+subs.introductoryPriceCycles, R.drawable.ic_wallet, false, false); } }
Now come on your SubscriptionActivity.java
public class SubscriptionActivity extends Activity { InappBilling_Class inapp; private BillingProcessor bp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_subscription); ... inapp = new InappBilling_Class(SubscriptionActivity.this, bp); bp = inapp.initMethod(); .... } @Override protected void onResume() { super.onResume(); inapp.updateTextViews(3); } @Override public void onDestroy() { if (bp != null) bp.release(); super.onDestroy(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (!bp.handleActivityResult(requestCode, resultCode, data)) super.onActivityResult(requestCode, resultCode, data); System.out.println("**********" + data.getData() + "**********"); }}
Enjoy your subscription/ Products showing In-App.
- 4 years ago
public void updateTextViews(int ia) { if(!SUBSCRIPTION_ID.isEmpty()) { i++; // TextView protext = (TextView)findViewById(R.id.productIdTextView); // protext.setText(String.format("%s is%s purchased", PRODUCT_ID, bp.isPurchased(PRODUCT_ID) ? "" : " not")); // TextView subtext = (TextView)findViewById(R.id.subscriptionIdTextView); // subtext.setText(String.format("%s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not")); showToast(String.format(" %s is%s subscribed", SUBSCRIPTION_ID, bp.isSubscribed(SUBSCRIPTION_ID) ? "" : " not") + " | " + SUBSCRIPTION_ID); if (bp.isSubscribed(SUBSCRIPTION_ID)) { showSunscriptionDetails(); } else { showToast(String.format("is not subscribed") + " | " + SUBSCRIPTION_ID); } } }
why did you comment first 4 lines of the code in method?
- 4 years ago
Add Customize Dialog Class
import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.graphics.drawable.Drawable; import android.support.v7.app.AlertDialog; public class CustomeDialogClass { public static void show(final Dialog dialog, String title, boolean cancelable) { dialog.setContentView(R.layout.custome_progressdialog_lay); dialog.setTitle(title); dialog.setCancelable(cancelable); /*//there are a lot of settings, for dialog, check them all out! //set up text TextView text = (TextView) dialog.findViewById(R.id.TextView01); text.setText(R.string.lots_of_text); //set up image view ImageView img = (ImageView) dialog.findViewById(R.id.ImageView01); img.setImageResource(R.drawable.nista_logo); //set up button Button button = (Button) dialog.findViewById(R.id.Button01); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { finish(); } });*/ //now that the dialog is set up, it's time to show it /* if (startStop) { dialog.show(); } else { dialog.dismiss(); } Toast.makeText(getBaseContext(), startStop + "", Toast.LENGTH_SHORT).show();*/ dialog.show(); } public static void yesNoDialogBox(final AlertDialog.Builder dialog, String title, String msg, int icon, boolean cancelable) { //AlertDialog.Builder builder = new AlertDialog.Builder(this); dialog.setTitle(title); dialog.setIcon(icon); dialog.setCancelable(cancelable); dialog.setMessage(msg); /*dialog.setPositiveButton("Delete", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { onBackPressed(); } });*/ dialog.setNegativeButton("Not Now", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); AlertDialog dialogs = dialog.create(); // display dialog dialogs.show(); } public static void oKDialogBox(final AlertDialog.Builder dialog, String title, String msg, int icon, boolean cancelable, boolean nativebtn) { //AlertDialog.Builder builder = new AlertDialog.Builder(this); dialog.setTitle(title); dialog.setIcon(icon); dialog.setCancelable(cancelable); dialog.setMessage(msg); /*dialog.setPositiveButton("Delete", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { onBackPressed(); } });*/ if (nativebtn) { dialog.setNegativeButton("Okay!", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); } AlertDialog dialogs = dialog.create(); // display dialog dialogs.show(); } }
Hot Questions