Archive for the ‘Guide – Google Services for Android’ Category

Guide: Google Services for Android : In-App Purchase:

It was a long time since my last update here and this time I want to talk about a topic that
has a great importance to me, as I manage a lot of it in recent at my current work location.
For this reason I have decided to take a moment and write an informative guide for the
integration of In-App Purchase feature in your application.

So to integrate In-App purchase feature in you application you have to follow a few simple steps:

1. First of all we will add a permission to the Manifest file:

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

2. Next you will need to get a license key for the In-App Purchase process from the Google Play Administration Console. You can get it in a couple of ways one is by clicking the “Prepare Store Listing” button when adding a new application to the store.
To start this process press the Add new application button at the main screen of the developer’s console:

add_new_application

2.1. Then enter a default language for your application.
2.2. Give you application a title to display in Google Play store.
2.3. Press the Prepare Store Listing button to add additional information for the application.

Alternatively you could chose to upload an application’s APK that has the permission from
first step and this way Google will know that our app has an In App Purchase feature and will let us get the key.

To get the key open the developer console and go to the Services & APIs section.
Under the LICENSING & IN-APP BILLING section. You will find a YOUR LICENSE KEY FOR THIS APPLICATION which will have you application’s license key. You will need to add it to your application later on.

3. Now that you have a key it’s time to add an in app product to you application, in the developer console open the In-App Products section and press the Add New Product button, you will receive the
following window:

in_app_product_explained

3.1. Selected the manage product, manage product are product that Google manages for
you in their data bases, basically you can latter on query their databases for the status of
this item for the user of your application.

3.2. Enter an id for this product (Important: this id can’t be changed after it entered) and press Continue. Next a page will be opened when you will have to
add some other details for this product as it Name (that will be shown for the users), Price
and Description.

Now that we finished with the console configuration lets start implementing the feature in our
application:

4. First of all we will need to download the Google Play Billing Library from the
SDK Manager. Once have done it, this will result in downloading an example project
that will be located at the following folder:

/extras/google/play_billing

4.1. You will need to copy from this project the IInAppBillingService.aidl file including all of it’s folder’s structure. So this file must be added into the following path: com.android.vending.billing

4.2. In addition one of this project’s folders is called utils, and includes Google’s Helper classes to handle the In-App Purchase flow. So you will need to copy this folder to your project.

At the end of this process your project structure should look like this:

project_structure

5.1. Now lets start with the coding. First of all we will setup the helper class:

public class MainActivity extends Activity {
    IabHelper mHelper;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        String base64EncodedPublicKey = "<your license key goes here>";
        mHelper = new IabHelper(this, base64EncodedPublicKey);
        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
            public void onIabSetupFinished(IabResult result) 
            {
                if (!result.isSuccess()) {
                    Log.d(TAG, "Problem setting up in-app billing: " + result);
                    return;
                }

                // Have we been disposed of 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.");
            });
        } 
.....
}

5.2. Next we will need to add product details (its id) to the application, as well as to add some
kind of a trigger to make a purchase of the in-app product, So I will add a button called bBuyFirstItem to my layout and add those lines to my code:

//an int to count the product.
int firstCount = 0;

//product id in the google play (the one you entered when adding the product in the developers console)
static final String SKU_FIRST_ITEM = "first";

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

Button bBuyFirstItem = (Button) findViewById(R.id.bBuyFirstItem);

bBuyFirstItem.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d(TAG, "Launching purchase flow for first item.");
        String payload = "";
        mHelper.launchPurchaseFlow(this, SKU_FIRST_ITEM, RC_REQUEST, mPurchaseFinishedListener, payload);
    }
});

5.3. Now we need to add a trigger for successful purchase, and the verifyDeveloperPayload method:

 // 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()) { return; }

    if (!verifyDeveloperPayload(purchase)) { return; }

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

    if (purchase.getSku().equals(SKU_FIRST_ITEM)) {
        // bought 1 first item, consume it.
        Log.d(TAG, "Purchase is first item. Starting item consumption.");
        firstCount++;
    }
};

/** 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;
}

5.4. You could also query the Google servers for managed products to get
the status of a product for the user account:

//to run a query run this method at the end of the helper object setup process
mHelper.queryInventoryAsync(mGotInventoryListenerMain);

//You also will need to create the listener:
IabHelper.QueryInventoryFinishedListener mGotInventoryListenerMain = 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()) { 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().
        */

        Purchase firstItemPurchase = inventory.getPurchase(SKU_FIRST_ITEM);
        boolean mIsFirstItem = (firstItemPurchase != null && verifyDeveloperPayload(firstItemPurchase));
        if (mIsFirstItem) {
             mHelper.consumeAsync(firstItemPurchase, null);
        }
        Log.d(TAG, "User owns: " + (mIsFirstItem ? "FIRST ITEM" : "NOT FIRST ITEM"));
        Log.d(TAG, "Initial inventory query finished; enabling main UI.");
    }
};

That’s it for now, hope this will help you to start with integrating the In-App Purchase
feature in your application. Enjoy and Stay tuned :)