Implementing Remove Ads in app Purchases in Android Tutorial Example

By | May 12, 2016

In this tutorial we will quickly setup and integrate in app purchases in Android Apps/Games.

Steps needed for Implementation:

  1. Adding In App Billing Library using Android SDK Manager
  2. Setting up Google Play Developer Console
  3. Getting Required keys from Developer Console.
  4. Coding part

A Little Overview about how Google Play in-app purchases work

Before we begin, we need to know about how actually android in-app purchases work. In Android in-app purchases are made using either in app Billing Library OR Android Pay.

Android Pay:
Android Pay is used as wallet for making payments of non- digital goods. Its NOT of our use right now. You can learn more about it here.

In-App Billing:

In-app Billing is a Google Play service that lets you sell digital content from inside your applications. Thats what we will use today.





How in-app Billing actually works:

When making an in-app purchase, you actually buy a product from google. Consider it as a marketplace similar to Amazon where a seller puts his products for sale and users buy it from there. Similarly a developer needs to add a product in his developer console of his particular app. For example “Remove Ads” is a product which is added in the Google Play developer console for a particular app. When users pay for removing ads for a game/app, they actually buy the product from Developer Console of the developer.

Lets talk about the type of products. There are mainly two types for products in Android in app Billing.

  1. Managed Product – Its a type of product which a buyer pays for once. In other words, buyer owns the product for lifetime after making the purchase, and he cannot buy that same product ever again. If developer has given an interface to buy the same product again, it will throw an error. But these products can also be set as consumed for a particular buyer. And a consumed product can be bought again!

    Example of Consumable Managed Product:
    For example when a user buys a pack of 600 gems in a game, he buys a product named “600 Gems“. But as soon as the user buys 600 gems, this product is set as consumed so that it can be purchased again.

    Example of Simple Managed Product:
    This is a simple purchase of Managed Product. For example a user buys “Remove Ads” product which has to be owned for life time. So it cannot be purchased again by the same user. Developer do not write any code for consuming the product after purchase.

  2. Subscription – The name itself says it all. It a subscription of any service. For example a purchase for unlimited fuel for one month in car racing game (Example of the Sample In App Billing App provided by Google).

Lets Begin…

Adding In App Billing Library using Android SDK Manager

Step 1) Download Billing Library from Android SDK Manager as shown below:

Download Android in app billing library

Thats it! Rest we will see in the coding part 🙂

Setting up Google Play Developer Console

Step 1) Login to Google Play Developer Console and select YOUR_APP-> in-app Products. You need to setup merchant account for in-app billing. Its a simple form you need to fill. Then for adding products there, you need an apk with required Billing permission to be uploaded in the Developer console. So simply modify your exiting app’s AndroidManifest.xml file to add the following permission and upload that apk to alpha or Beta Testing :

    <uses-permission android:name="com.android.vending.BILLING" />

Step 2) Now you are eligible to add a product as in-app Product for your app. So add a product named “Remove Ads” as a Managed Product and provide other necessary details.

Step 3) Now add test users for making test purchases for your product by going to Developer Console-> Settings -> Account Details. Look at the image shown below.

Integrating In app purchases in android

Getting Required keys from Developer Console

Step 1) Note down the Product ID which you provided for the new product.

Step 2) Note down the Public Key of the app in which you are integrating in app billing. This can be obtained by going to Developer Console-> YOUR_APP-> Service & Apis. Look at the screenshot below:

Integrating In app billing Android

Coding part

Step 1) Open the sample app provided along with the in-app billing library you downloaded from Android SDK Manager. It will be located at : ANDROID_SDK_LOCATION/extras/google/play_billing

Lets look at the java classes provided in the Sample app:
In App Billing Sample App

Step 2) Create a new Package named com.android.vending.billing in your Android app and copy the file from the Sample app to your project’s this newly created package. Look below how I added this to my own project:

Inapp Billing File Copy

Step 3) Now Copy the complete package named “com.example.android.trivialdrivesample.util” along with its all java files to your own project. You can rename this package. These java files are required for in-app billing. You have to use them as it is for any project which requires in-app purchase integration.

Step 4) Now let do the final Integration of the in app purchases!

Create a new File named MyBillin.java with the following content:

package com.marothiatechs.apis;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.util.Log;

import com.marothiatechs.ZBHelpers.Constants;
import com.marothiatechs.gatepuzzle.billing.utils.IabHelper;
import com.marothiatechs.gatepuzzle.billing.utils.IabResult;
import com.marothiatechs.gatepuzzle.billing.utils.Inventory;
import com.marothiatechs.gatepuzzle.billing.utils.Purchase;

public class MyBilling {
	// Debug tag, for logging
	static final String TAG = "GatePuzzle";

	static final String SKU_REMOVE_ADS = "YOUR_PRODUCT_ID";

	// (arbitrary) request code for the purchase flow
	static final int RC_REQUEST = 10111;

	Activity activity;

	// The helper object
	IabHelper mHelper;

	String base64EncodedPublicKey = "YOUR_PUBLIC_KEY";
	Boolean isAdsDisabled = false;
	String payload = "ANY_PAYLOAD_STRING";

	public MyBilling(Activity launcher) {
		this.activity = launcher;
	}

	public void onCreate() {

		// Create the helper, passing it our context and the public key to
		// verify signatures with
		Log.d(TAG, "Creating IAB helper.");
		mHelper = new IabHelper(activity, base64EncodedPublicKey);

		// enable debug logging (for a production application, you should set
		// this to false).
		mHelper.enableDebugLogging(false);

		// Start setup. This is asynchronous and the specified listener
		// will be called once setup completes.
		Log.d(TAG, "Starting setup.");
		mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
			public void onIabSetupFinished(IabResult result) {
				Log.d(TAG, "Setup finished.");

				if (!result.isSuccess()) {
					// Oh noes, there was a problem.
					// complain("Problem setting up in-app billing: " + result);
					return;
				}

				// Have we been disposed off in the meantime? If so, quit.
				if (mHelper == null)
					return;

				// IAB is fully set up. Now, let's get an inventory of stuff we
				// own.
				Log.d(TAG, "Setup successful. Querying inventory.");
				mHelper.queryInventoryAsync(mGotInventoryListener);
			}
		});
	}

	// Listener that's called when we finish querying the items and
	// subscriptions we own
	IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
		public void onQueryInventoryFinished(IabResult result,
				Inventory inventory) {
			Log.d(TAG, "Query inventory finished.");

			// Have we been disposed of in the meantime? If so, quit.
			if (mHelper == null)
				return;

			// Is it a failure?
			if (result.isFailure()) {
				// complain("Failed to query inventory: " + result);
				return;
			}

			Log.d(TAG, "Query inventory was successful.");

			/*
			 * Check for items we own. Notice that for each purchase, we check
			 * the developer payload to see if it's correct! See
			 * verifyDeveloperPayload().
			 */

			// Do we have the premium upgrade?
			Purchase removeAdsPurchase = inventory.getPurchase(SKU_REMOVE_ADS);
			Constants.isAdsDisabled = (removeAdsPurchase != null && verifyDeveloperPayload(removeAdsPurchase));
			removeAds();

			Log.d(TAG, "User has "
					+ (Constants.isAdsDisabled ? "REMOVED ADS"
							: "NOT REMOVED ADS"));

			// setWaitScreen(false);
			Log.d(TAG, "Initial inventory query finished; enabling main UI.");
		}
	};

	// User clicked the "Remove Ads" button.
	public void purchaseRemoveAds() {

		activity.runOnUiThread(new Runnable() {

			@Override
			public void run() {

				mHelper.launchPurchaseFlow(activity, SKU_REMOVE_ADS,
						RC_REQUEST, mPurchaseFinishedListener, payload);

			}
		});
	}

	public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
		Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + ","
				+ data);
		if (mHelper == null)
			return true;

		// Pass on the activity result to the helper for handling
		if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
			// not handled, so handle it ourselves (here's where you'd
			// perform any handling of activity results not related to in-app
			// billing...
			return false;
		} else {

			Log.d(TAG, "onActivityResult handled by IABUtil.");

			return true;
		}

	}

	/** Verifies the developer payload of a purchase. */
	boolean verifyDeveloperPayload(Purchase p) {
		String payload = p.getDeveloperPayload();

		/*
		 * TODO: verify that the developer payload of the purchase is correct.
		 * It will be the same one that you sent when initiating the purchase.
		 * 
		 * WARNING: Locally generating a random string when starting a purchase
		 * and verifying it here might seem like a good approach, but this will
		 * fail in the case where the user purchases an item on one device and
		 * then uses your app on a different device, because on the other device
		 * you will not have access to the random string you originally
		 * generated.
		 * 
		 * So a good developer payload has these characteristics:
		 * 
		 * 1. If two different users purchase an item, the payload is different
		 * between them, so that one user's purchase can't be replayed to
		 * another user.
		 * 
		 * 2. The payload must be such that you can verify it even when the app
		 * wasn't the one who initiated the purchase flow (so that items
		 * purchased by the user on one device work on other devices owned by
		 * the user).
		 * 
		 * Using your own server to store and verify developer payloads across
		 * app installations is recommended.
		 */
		return true;
	}

	// Callback for when a purchase is finished
	IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
		public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
			Log.d(TAG, "Purchase finished: " + result + ", purchase: "
					+ purchase);

			// if we were disposed of in the meantime, quit.
			if (mHelper == null)
				return;

			if (result.isFailure()) {
				complain("Error purchasing: " + result);
				return;
			}
			if (!verifyDeveloperPayload(purchase)) {
				complain("Error purchasing. Authenticity verification failed.");
				return;
			}

			Log.d(TAG, "Purchase successful.");

			if (purchase.getSku().equals(SKU_REMOVE_ADS)) {
				// bought the premium upgrade!
				removeAds();

			}
		}
	};

	private void removeAds() {
		isAdsDisabled = true;
	}

	// We're being destroyed. It's important to dispose of the helper here!

	public void onDestroy() {

		// very important:
		Log.d(TAG, "Destroying helper.");
		if (mHelper != null) {
			mHelper.dispose();
			mHelper = null;
		}
	}

	void complain(String message) {
		Log.e(TAG, "**** TrivialDrive Error: " + message);
		alert("Error: " + message);
	}

	void alert(final String message) {
		activity.runOnUiThread(new Runnable() {

			@Override
			public void run() {

				AlertDialog.Builder bld = new AlertDialog.Builder(activity);
				bld.setMessage(message);
				bld.setNeutralButton("OK", null);
				Log.d(TAG, "Showing alert dialog: " + message);
				bld.create().show();
			}
		});
	}

}

Replace the Strings:
YOUR_PRODUCT_ID with the product id you noted down.
YOUR_PUBLIC_KEY with public key you noted down.
ANY_PAYLOAD_STRING can be replaced with anything. It can even be left as it is.




Now lets see what we have actually done in the MyBilling.Java file.

We have created this separate file where all the billing related tasks can be done. It is separated from your app’s main activity. There are some methods similar to the names of an Activity’s default methods such as..
onCreate();
onDestroy();
onActivityResult();

Simply create an instance of MyBilling.java in your main Activity class and call the above methods at there respective places.

Now look at the method purchaseRemoveAds() This is the method which should be called when a user clicks on “Remove Ads” Button provided in by you in your app. Simply provide an interface for making a purchase and call this purchaseRemoveAds() to initiate the purchase flow.

Thats All! You can go through the code for better knowledge about how the in app purchase flow is working in the MyBilling.java file.

6,069 total views, 10 views today

(Visited 4,966 times, 16 visits today)
  • http://www.ekamus.info/ Apichat

    What com.marothiatechs.ZBHelpers.Constants contains?

    • Laxman Marothiya

      Constants.java contains some constant variables. You can use your own variables in place of them.