[TUT] Simple InApp Billing / Payment V3

Google have released a new version of their In App Billing (Version 3). So I’ve followed suit and updated my tutorial!

Eclipse Project Source Code Download

GitHub Source Code Repo Link

There are a fair few changes, too many to fit into one tutorial but the overview is:

All purchases are now managed purchases
This means that once a user buys your item they own it, you have to ‘consume the purchase’ if you want to allow it to be purchased again. This is used in this tutorial but not explained or coded in a clean way so it is left for my next tut.
The benefits of this are that all purchases will be stored by Google Play and it will be easy to retrieve the status of whether a user has already purchased an item.

The Android team have released a ‘helper’ class
This is to make in app purchases that much simpler. It has a vague resemblance to my original ‘BillingHelper’ class only it is called ‘IabHelper’ .. very interesting. This helper class makes things a hell of a lot easier.

Let’s get straight into it.

To start with I’d like to say, this isn’t the only way to do this. I myself have followed the developer tutorials on developer.android and managed to create this test project which I can now use as a reference when making other projects. Feel free to comment on the style and ask any questions. I would recommend you download the test project I have attached rather than copy and paste, this will stop minor syntax errors.

Developer.Android Links:
Google Billing Overview
Google Billing Integration

Ok first the outline.

Were going to create and app that has one button, when you click this button it informs the android market you want to make a purchase. On confirmation of this purchase you have bought a picture of a passport and it is shown to you in the app.

Simple setup stuff will be skipped (it is all in the download source).

First you create your project with the IInAppBillingService.aidl file included. You then need to add the Billing Helper classes, look at the source code, I have added these in the android.vending.billing.util package. They are the same as the Android example except the IabHelper which I have modified when I found some slight bugs.

Create 3 Activities, the first is the start up activity. This checks if In App Purchase is available on the device. If it is we load the main activity if it isn’t we don’t let them go any further:

StartUpActivity.java

package com.blundell.tutorial.simpleinappbillingv3.ui;

import android.os.Bundle;

import com.android.vending.billing.util.IabHelper.OnIabSetupFinishedListener;
import com.android.vending.billing.util.IabResult;
import com.blundell.tutorial.simpleinappbillingv3.ui.base.PurchaseActivity;
import com.blundell.tutorial.simpleinappbillingv3.util.Log;

/**
 * Checks that In App Purchasing is available on this device
 * 
 * @author Blundell
 * 
 */
public class StartUpActivity extends PurchaseActivity implements OnIabSetupFinishedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("App started");
    }

    @Override
    public void onIabSetupFinished(IabResult result) {
        if (result.isSuccess()) {
            Log.d("In-app Billing set up" + result);
            dealWithIabSetupSuccess();
        } else {
            Log.d("Problem setting up In-app Billing: " + result);
            dealWithIabSetupFailure();
        }
    }

    @Override
    protected void dealWithIabSetupSuccess() {
        navigate().toMainActivity();
        finish();
    }

    @Override
    protected void dealWithIabSetupFailure() {
        popBurntToast("Sorry In App Billing isn't available on your device");
    }
}

This StartUpActivity extends the PurchaseActivity. The PurchaseActivity is what talks to the Android helper service. Whenever the activity is created it will check that in app billing is still supported at this time.

PurchaseActivity.java

package com.blundell.tutorial.simpleinappbillingv3.ui.base;

import android.content.Intent;
import android.os.Bundle;

import com.android.vending.billing.util.*;
import com.android.vending.billing.util.IabHelper.OnIabPurchaseFinishedListener;
import com.android.vending.billing.util.IabHelper.OnIabSetupFinishedListener;
import com.blundell.tutorial.simpleinappbillingv3.AppProperties;
import com.blundell.tutorial.simpleinappbillingv3.R;
import com.blundell.tutorial.simpleinappbillingv3.domain.items.Passport;
import com.blundell.tutorial.simpleinappbillingv3.util.Log;

/**
 * This class should be the parent of any Activity that wants to do in app purchases
 * it makes our life easier by wrapping up the talking to the IabHelper and just exposing what is needed.
 * 
 * When this activity starts it will bind to the Google Play IAB service and check for its availability
 * 
 * After that you can purchase items using purchaseItem(String sku) and listening for the result
 * by overriding dealWithPurchaseFailed(IabResult result) and dealWithPurchaseSuccess(IabResult result, Purchase info)
 * 
 * @author Blundell
 * 
 */
public abstract class PurchaseActivity extends BlundellActivity implements OnIabSetupFinishedListener, OnIabPurchaseFinishedListener {

    private IabHelper billingHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_purchase);
        setResult(RESULT_CANCELED);

        billingHelper = new IabHelper(this, AppProperties.BASE_64_KEY);
        billingHelper.startSetup(this);
    }

    @Override
    public void onIabSetupFinished(IabResult result) {
        if (result.isSuccess()) {
            Log.d("In-app Billing set up" + result);
            dealWithIabSetupSuccess();
        } else {
            Log.d("Problem setting up In-app Billing: " + result);
            dealWithIabSetupFailure();
        }
    }

    protected abstract void dealWithIabSetupSuccess();

    protected abstract void dealWithIabSetupFailure();

    protected void purchaseItem(String sku) {
        billingHelper.launchPurchaseFlow(this, sku, 123, this);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        billingHelper.handleActivityResult(requestCode, resultCode, data);
    }

    /**
     * Security Recommendation: When you receive the purchase response from Google Play, make sure to check the returned data
     * signature, the orderId, and the developerPayload string in the Purchase object to make sure that you are getting the
     * expected values. You should verify that the orderId is a unique value that you have not previously processed, and the
     * developerPayload string matches the token that you sent previously with the purchase request. As a further security
     * precaution, you should perform the verification on your own secure server.
     */
    @Override
    public void onIabPurchaseFinished(IabResult result, Purchase info) {
        if (result.isFailure()) {
            dealWithPurchaseFailed(result);
        } else if (Passport.SKU.equals(info.getSku())) {
            dealWithPurchaseSuccess(result, info);
        }
        finish();
    }

    protected void dealWithPurchaseFailed(IabResult result) {
        Log.d("Error purchasing: " + result);
    }

    protected void dealWithPurchaseSuccess(IabResult result, Purchase info) {
        Log.d("Item purchased: " + result);
        // DEBUG XXX
        // We consume the item straight away so we can test multiple purchases
        billingHelper.consumeAsync(info, null);
        // END DEBUG
    }

    @Override
    protected void onDestroy() {
        disposeBillingHelper();
        super.onDestroy();
    }

    private void disposeBillingHelper() {
        if (billingHelper != null) {
            billingHelper.dispose();
        }
        billingHelper = null;
    }
}

Then our MainActivity, this just has the button for purchasing a passport. It will also receive a callback saying if the passport was bought or not.

The MainActivity starts the PurchasePassportActivity using startActivityForResult, this is how we inform it of a purchase. As with the StartUpActivity the PurchasePassportActivity extends our PurchaseActivity allowing it to talk to the Google Play Billing Service (and it’s helper class).

When the PurchasePassportActivity is started, it will get a callback saying billing is available and go onto to purchase the passport. The only thing special in this Activity is that is passed the SKU (the items ID from Google Play) to the Helper service. In this tutorial we use the “android.test.purchased” SKU meaning purchases will always be successful.

PurchasePassportActivity

package com.blundell.tutorial.simpleinappbillingv3.ui;

import android.os.Bundle;

import com.android.vending.billing.util.IabResult;
import com.android.vending.billing.util.Purchase;
import com.blundell.tutorial.simpleinappbillingv3.domain.items.Passport;
import com.blundell.tutorial.simpleinappbillingv3.ui.base.PurchaseActivity;

/**
 * This activity will purchase a Passport from Google Play.
 * 
 * If you wanted to change to purchase something else all you have to change is the SKU (item id) that is used
 * you could even pass this in as an Intent EXTRA to avoid duplication for multiple items to purchase
 * 
 * N.B that we extend PurchaseActivity if you don't understand something look up to this class
 * 
 * @author Blundell
 * 
 */
public class PurchasePassportActivity extends PurchaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Set the result as cancelled in case anything fails before we purchase the item
        setResult(RESULT_CANCELED);
        // Then wait for the callback if we have successfully setup in app billing or not (because we extend PurchaseActivity)
    }

    @Override
    protected void dealWithIabSetupFailure() {
        popBurntToast("Sorry buying a passport is not available at this current time");
        finish();
    }

    @Override
    protected void dealWithIabSetupSuccess() {
        purchaseItem(Passport.SKU);
    }

    @Override
    protected void dealWithPurchaseSuccess(IabResult result, Purchase info) {
        super.dealWithPurchaseSuccess(result, info);
        setResult(RESULT_OK);
        finish();
    }

    @Override
    protected void dealWithPurchaseFailed(IabResult result) {
        super.dealWithPurchaseFailed(result);
        setResult(RESULT_CANCELED);
        finish();
    }

}

Note- The code below in the PurchaseActivity.java would be removed if you wanted to use this. It is there because the new version of in app billing treats all purchases as “managed items” i.e. when you buy them once you own them until you use them or they are refunded. So this code automatically ‘refunds’ the purchase so the demo doesn’t just work first time!

// DEBUG XXX
// We consume the item straight away so we can test multiple purchases
billingHelper.consumeAsync(info, null);
// END DEBUG

That’s it, the rest of the code are just helpers and comments to try and explain what is going on and making it easier to extend.

As I always say This code tutorial isn’t foolproof and I feel I may of swept over a few things. But I really want to just give an alternative to the tutorial that is on the developer.android site. You could read this and understand the smaller concepts then go on to make a better implementation.

If you want to productionise this code you will want to go away and look at some of the security tutorials, obfuscation etc.

Remember to say thanks and enjoy!

Here are the code links again:

Eclipse Project Source Code Download

GitHub Source Code Repo Link

95 thoughts on “[TUT] Simple InApp Billing / Payment V3

  1. I used your sample code. It works fine till purchasing. But after purchasing I have to get the purchase credentials through my app. I call a service api from method “onSuccessfulPurchased” and pass the purchase class variable as the parameter, But my service is not working. I guess it is not called from that class.
    Please help me to resolve this issue.
    You can contact me through my mail too.

    Thanks.

  2. If the screen is rotated several times when PurchasePassportActivity is up, several instances of this activity are created on top of one another. A purchase under these conditions becomes unmanageable. Thanks for sharing.

    1. For that, you need your build to published on the play store as well as your products along with it on the play store. The product id is what you give while adding the product. Use that product id in place of “android.test.purchased” assigning to the variable SKU, probably existing in Passport class of the sample.

  3. Hello,

    In my App,I want to implement InApp Purchases.I got SKU and Base 64. I don’t want managed purchases but instead consume the purchase(because I want to purchase the product again).

    so currently In the IaBHelper.java code,
    If I change the following constant
    public static final String ITEM_TYPE_INAPP = “subs”; for consume the purchase.Is my InApp works for consume?

  4. Hi,

    Thanks for the tutorial. It helps for the beginners like me.

    I have Integrated this to my app. And I am using “android.test.purchased” as the SKU.

    I am getting this response:

    “IAB helper created.

    Starting in-app billing setup.

    Billing service connected.

    Checking for in-app billing 3 support.

    In-app billing version 3 supported for com.bab.mtadawul

    In-app Billing set upIabResult: Setup successful. (response: 0:OK)”

    and also ” Starting async operation: launchPurchaseFlow

    Constructing buy intent for android.test.purchased

    Launching buy intent for android.test.purchased. Request code: 123

    D/OpenGLRenderer(26178): Flushing caches (mode 0)”

    on the console.

    and keep loading the loader on the device screen.

    Is my code work for real time SKU not with test SKU.

    please help.

  5. Hello blundell.

    Your tutorial is very helpful for me.

    But there are single problem.

    When I purchase any item once, then second time I click on purchase button it ask second time for puchase. So how to avoid this.

  6. Thanks for this great tutorial. I’ve got it running and am working through figuring out what happens when, and what bits are necessary so I can integrate it into my own app.

    Questions: is having passport & its SKU in a separate class part of obfuscation? I am still a noob at this, so code obfuscation is a whole world I’ve never been to. Would you consider using Proguard sufficient? Finally, I intend my app’s purchase to be a one-time upgrade to a no-ads version. Should I store an “upgrade purchased” boolean somewhere, and if so where? (I’ve heard both yes and no for SharedPreferences.) Or does the app communicate with the Play Store to get its licensing info (sounds safer but also more complex to code.)

  7. How do i integrate this inappbilling into my shopping cart app? My shopping cart only have one button for checkout which is similar to this tutorial.

  8. Hi there,
    I used your demo code and made a simple test app. I uploaded it on Google play, created in-app items and made them active. I can successfully get the list of items from it using billingHelper.queryInventoryAsync(true, additionalSkuList,
    new QueryInventoryFinishedListener() {

    @Override
    public void onQueryInventoryFinished(IabResult result,
    Inventory inv) {
    } method. Here inv object is refreshed successfully and I can list these items in my app.
    But I made another test app, and used the Base64 Key of previous app in my new app. But now I am not able to get the list of available items using the same code. Can you please tell me where I am going wrong.
    Please help

  9. hello
    When i try display dataSignature and purchaseData of your code.. i got purchase data but dataSignature is NULL why?
    i am also facing the same problem that in my test product id i am getting NULL value
    waiting for reply
    thank you

  10. i use this demo . but when i close application than for close error is occure.. i can’t understood why this error is come because i can’t start service..

  11. Very nice tutorial.

    But I have a question. I’ve found in Google documentation that exists a “Purchase Status API” (Google Play Android Developer API) to verify purchases in a backend server.

    Do you know how to use this API? I haven’t found any example, and Google documentation is not very good.

    Thanks

  12. i have implemented in-app billing in my project but How to implement Restore Transactions Functionality in this sample project please help me

  13. Hi,

    code works fine…so what line of code do i need to change if i want to purchase the item only once?
    I tried deleting

    billingHelper.consumeAsync(info, null);

    Like you said in your tutorial..and it allows me to purchase the item once, but then when i close the app down and then go back into the app and hoping that when i go to click the button again…it says i cant purchase it/access the app(something along those lines )… thoughts? is there a line of code i need to add so the app remembers i brought it and that i can now use it at will when ever i close the app and open it again? many thanks =)

  14. Excellent Tutorial, But Stuck at some place. The sample code itself worked fine, But when I tried with my own public key and my own package I get “ITEM NOT FOUND” error, So I did as you suggested used my own key but used TEST SKU, It works fine… So what is the problem with my package name,? I have uploaded my app in google play and it is in draft state … Pls advise

    1. You might just have to wait a little (for your draft to propagate to the google servers). Not sure on your project specifics

  15. Hello Sir,
    Your tutorials are very helpful for android developer(Beginners). When i run this project(Simple InApp Billing V3) on emulator then it only showing Loading. So please give me a help.

  16. Hi and thank you for the great tutorial.

    After my purchase success, I must send to a back-end server a base64 encoded receipt.
    In ios that would be the bianry DATA field.
    I see many attributes in the Purchase class. What would be the corresponding value in android?

  17. Thanks for sharing this helpful tutorial.This tutorial work fine ,

    But Im facing some problem by implement it.I changed the the BASE_64_KEY to my apps public key and the SKU to its inapp products id(Application name).
    But whenever i try to purchase the product, The google play says “ITEM NOT FOUND”.

    I also upload a draft application in my account(that give to BASE_64_KEY and products id) for testing.
    Is there anything i missed the condition ??Please help to me how can resolve it.

  18. I am about to implement in-app billing for ppurchasing a subscription. Does this code work for subscriptions? And is there a way to verify that a subscription is valid or not?

  19. On the official site, http://developer.android.com/google/play/billing/billing_reference.html#billing-interface
    it is said: getSkuDetails() returns a price as “Formatted price of the item, including its currency sign. The price does not include tax.”
    I want to have some clarifications:
    1. the price, even though is with currency code, it is the price the developer sets when he/she published the app, regardless of the buyer’s currency settings. Is this correct?
    2. If the first statement is true, is there anyway I can get the what currency the buyer actually paid for the app after the purchase is finished?

    Thanks, I have been looking through lots of docs regards to this issue, but have not found a satisfied answer.

    1. I would have thought it would be in the buyers local currency. When you sell your items Google Play can do automatic conversions to local currencys (unless you set the conversion yourself). So 1) is not correct.

  20. I have a situation where parts of the data retrieved from a certain service (players) should be available for subscription. I can’t find any information anywhere if it is possible to have multiple subscriptions running for the same ProductID.

    The business model is designed such that I can subscribe on specific information for a player for a certain period, but I do want to be able to have multiple players, without having to create Product ID’s for each and every one of them.

    Anyone knows?

  21. Hi ,

    Thanks for your nice tutorial!.One doubt!.If i modify the code for paid app and i change the public key,it works fine or not?.

  22. This seems like a possible glitch in IAB3:

    1. I used my own app to purchase a non-consumable item on my Nexus 7. This is a real (non-static) SKU but purchased using a test account, with the app defined as a draft (not published). The app is signed with the same key as the app I uploaded to Google Play store via the developer console, and has the same version number and version code. No problem with this purchase.

    2. I then ran my same signed app on my Nexus One, which has the same test account as its main user account. It performs a queryInventoryAsync when it starts up (and periodically subsequent to that). However, it does not see the new purchase, even though it is specifically checking for it. My Inventory request SUCCEEDS, but when I perform a inventory.getPurchase(MY_PURCHASED_SKU) it returns NULL.

    3. If, at this point (and this is only about 15 minutes from having made the purchase on the N7), I attempt to initiate a *new* PURCHASE of the item from the N1, I get a message that the item is already owned. So, Google’s servers clearly realize that I’ve purchased the item.

    4. Once I’ve *made* the purchase *attempt* from the N1, subsequent calls to queryInventoryAsync() *do* return a Purchase object for MY_PURCHASED_SKU, and the purchase state returned for that object by getPurchaseState() is Purchase.INAPP_PURCHASE_STATE_PURCHASED.

    In other words, my failed attempt to re-purchase the item from a device other than the one used to purchase the item initially seems to have added the missing purchase to subsequent results on that second (N1) device by somehow “forcing the issue” when I attempted to purchase it again.

    My question would be: Would the same thing have happened if I had just waited longer without trying to purchase the item? Would the purchase eventually have appeared? And, is this a known problem?

    1. OK, I’ve found that if I power down the N1 and power it back up again, then it *does* detect the purchase made on the Nexus 7, even without attempting a purchase from the N1. So some kind of updating of the Google Play app from the GP servers seems to occur at the point that the device is booted but not subsequently.

      This seems like a poor design functionally, but it is probably intended to conserve server bandwidth since if every app instance is probably checking every time the app starts (per recommended practice) they are not going to want to make a round trip to the server each time that occurs.

      1. Carl,

        You seem to have a lot of experience with this.

        Do you know the basics (or even have some sample code) on how to restore a purchase after an uninstall and re-install?

        Thanks.

  23. Thank you for good tutorial.

    but

    this line

    purchasesbillingHelper.consumeAsync(info, null);

    not work
    error is 5 : Developer Error

    is anroid.test.purchased not consumable ?

    1. Developer Error usually means that you’re testing with an app that is either signed differently than the APK you uploaded, or has a different version/version code than the APK that you uploaded.

  24. how to restore purchase in v3?
    here my condition :
    – using v3 i success buy item from my app with my second account credit card
    – when i check my dev checkout account, i got information that my item already bought by my second accound
    – i uninstall my app, clear data google play, and remove my second account
    – login again with my second account, install my app again, but my item didnt restore, i have to buy it again.
    how to make restore it?

  25. I have implemented this project ..but there is error in log.java
    i have no idea that how i will fixed it ..

    help me plzzzz.

  26. Hello,Blundell
    I am glade i ran across your site. I think it will help me. I will give it a try.
    You are more help than google. I made and app to teach the alphabet, and I really want to get it going. If i can’t get it working can i pay you to help me.
    Thanks,
    Marcus

  27. I am subscribing the product with this smaple code..I have already added the item in product list as subscription product..I have changed SKU in app..Still Showing Item not found…Please Help me

  28. i want ask something, i download your project and want import into eclipse. but the problems was always failed.

    [2013-02-26 13:43:33 – com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper] Parser exception for C:\Users\User\workspace\SimpleInAppPurchaseV3\AndroidManifest.xml: Premature end of file.
    [2013-02-26 13:43:33 – SimpleInAppPurchaseV3] Project has no target set. Edit the project properties to set one.
    [2013-02-26 13:43:34 – SimpleInAppPurchaseV3] Parser exception for /SimpleInAppPurchaseV3/AndroidManifest.xml: Premature end of file.

    so what i have to do?

    1. Right Click on the imported Project > Properties > Android > Select a target SDK (14) > Apply > Ok . Then do a project clean. If that doesn’t work create a project.properties file and add it there.

      1. thank you for fast response..
        i wanna ask how i can check that item already purchase with in app billing?so my item just can bought once..thank you

        1. one more question, if i add item with Managed product, so if i publish my app, and user buy item in my app once, when they want buy it again, they will get error already purchased??or we have to add some code to validate that?

  29. Some errata in my prior posts:

    Please ignore my reference to IN_APP_NOTIFY in item 4, as I believe that only pertains to IAB version 2, and not to version 3 which we are discussing.

    And, please replace my reference to INAPP_PURCHASE_STATE_REFUNDED with the number “2”; INAPP_PURCHASE_STATE_REFUNDED is a symbol that I’ve defined myself and thus is not in general use.

    1. Hi Carl, From a brief read it seems you are on track with all your points. Some where more statements than questions I guess, if you want more discussion just drop me an email.

  30. One more question to add to what I’ve just posted:

    I have personally experienced (and there are many similar complaints posted from other developers) that manually initiating a refund via Checkout (e.g., for a test purchase from the TrivialDrive app) takes *days* to result in a change to the purchase state of the product (to INAPP_PURCHASE_STATE_REFUNDED).

    If you agree with that assessment, then do you know whether that same kind of indeterminate delay occurs when android.test.refunded is used for testing purposes?

    1. Interesting, I’ve refunded orders but never checked the state of these refunds with the idea to seeing how long the delay is, sorry!

  31. I’m listing a few unelaborated points here, just to be sure that I understand them correctly. Please let me know if the following is correct or apocryphal:

    1. In the TrivialDrive sample app, there are two SKUs: SKU_GAS, which is consumable, and SKU-PREMIUM, which is a permanent (upgrade) purchase enabling certain features irreversibly.

    2. There is actually no difference between a consumable product like SKU_GAS and a permanently purchased product like SKU_PREMIUM, so far as the definition of those products in Google Play is concerned, and so far as the handling of these products by Google Play (both app and store) is concerned. Any difference between consumable and non-consumable products is based solely on how they are handled by your app.

    Specifically, consumable products are consumed as soon as they are purchased via the IabHelper class’ consumeAsync(), while non-consumable products are not.

    3. Therefore as a practical matter, when testing, you are recommending the use of consumeAsync() in order to reset an android.test.purchased purchase back to a non-purchased state, so that the act of purchasing that test product can be repeated. It does not matter whether your app will treat the actual product to eventually be used in place of android.test.purchased as consumable or not; this same call to consumeAsync() can be used for testing purposes in either case.

    For consumable products, that call (to consumeAsync() will stay in your code, but for non-consumable ones, it will be removed prior to deployment.

    4. A call to android.test.refunded would also seem to provide a way of sorts to repeat the purchase of an item (although not to “unpurchase” it). The effect, in theory, if I understand it correctly, will be to generate the IN_APP_NOTIFY message that would accompany the refund of an actual product, normally initiated by the developer from the Google Play developer console. This should cause subsequent purchase objects returned by queryInventoryAsync() for that product to return a purchase state of INAPP_PURCHASE_STATE_REFUNDED.

    5. Use of android.test.refunded does not reset the purchase to a state as if “it never was,” as your consumeAsync() does very usefully for testing purposes. But it does allow the static product to be repurchased through a subsequent use of android.test.purchased.

    Is all, or any, of the above correct?

  32. what should i give inplace of SKU = “android.test.purchased” to make my application live?Should I pass My application package name?

  33. Great tutorial!
    I have a few questions though. First, what are the benefits of upgrading to version 3 of the IAB library?
    Also, do you think you could create a tutorial for upgrading to version 3 for those of us that have already implemented version 2 through your other tutorial?
    Thank you very much!

    1. I wouldn’t say there is an upgrade route, you have to remove the old AIDL and implement the new one. Version 3 is much simpler to integrate and more helper code in the libraries. I’d upgrade because one day they will deprecate fully v2.

      1. Also, if I were to use your method to implement IAB, I would not be able to use HoloEverywhere right? Because the main Activity extends PurchaseActivity and not Activity.

  34. Hi,

    Thanks for sharing this helpful tutorial.

    Im facing some problem…
    I changed the the BASE_64_KEY to my apps public key and the SKU to its inapp products id.
    But whenever i try to purchase the product, The google play says “ITEM NOT FOUND”.
    Is there anything i missed??

    Please help….

    1. I assume you have created the product in GPlay and uploaded a version of your app? Have you tried with the test purchase SKU and that works? If so it just sounds like the play hookup.

  35. Hi there,

    I keep getting an error: In-app billing error: Unable to buy item, Error response: 7:Item Already Owned

    I have implemented almost all your code.. But the purchase is not consumed.. Do you have any suggestions?

  36. Hey Blundell,

    Thanks again for updating your tutorial, they are always a great place to start!

    When I purchase an item (test item) I don’t get a signature returned in the purchase object. What causes this?

    FYI I am using the app with my key, and it has been uploaded to google.

    Thanks again,

    James

    1. I have a vague memory of this. Is it because you are using the android test item? and if you used your own item i.e. paid for it, you would get the signature

      1. If anyone is reading this…. Using real published products with an uploaded (signed) apk works just fine. You get the signature returned fine.

        You don’t need to actually publish the app, just upload it to the market place as a “new apk”.

  37. just now I run your demo in my galax 2 ,the log is :
    01-08 10:56:16.835: D/SIAPv3(7743): Data signature:

    and I use myself public key

      1. Thanks for your reply! I have uploaded my app to Google Play and get the public key ,but when run my app,I can not get signature .
        And I test my application in accordance with the Google test document inside the form of the second test?I use the developer account,but I can not get signature ,Is it because I was in China?Hope your reply!Thanks

  38. Hi,I use the demo of google , I found I could not get signature when I test the demo ,Do you meet this question ? Maybe you can help me please help me, Thanks!

  39. Blundell,

    Thanks for updateing your tutorial.

    If something is purchased using the new billing system, will the purchase now automatically be restored after an uninstall – reinstall?

    Thanks

  40. Hi i have tried this sample app its working fine. When i tried the google sample in app TrivialDrive im receiving a error message “User is not eligible to this purchase error”. What might be the reason? Can you help me ? Thanks in advance

      1. I haven’t bought the item not even single time.For the first time im trying to buy a in-app it is navigating to market place showing the in-app page and its description etc but immediately im receiving a message that “User is not eligible to this purchase error” with heading “item unavailable”

Leave a Reply

Your email address will not be published. Required fields are marked *