8

I working with a sample of in-ap purchase. My application have 2 buttons, first button was disable by default, click on second button will purchase and enable the first button. The purchase button work correct but after purchase, I've check the inventory but it's always return null, it's mean I haven't purchased yet.

Here is the source code:

Setup:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    buyButton = (Button) findViewById(R.id.buyButton);
    clickButton = (Button) findViewById(R.id.clickButton);
    clickButton.setEnabled(false);
    String base64EncodedPublicKey = "key";
    mHelper = new IabHelper(this, base64EncodedPublicKey);

    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                Log.d(TAG, "In-app Billing setup failed: " + result);
            } else {
                Log.d(TAG, "In-app Billing is set up OK");
            }
            // Query to detect user was buy this item or not
            mHelper.queryInventoryAsync(mReceivedInventoryListener);
        }
    });

    buyButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            if (clickButton.isEnabled()) {
                mHelper.queryInventoryAsync(mReceivedInventoryListener);
            } else {
                buyClick(v);
            }
        }
    });
}

The buy item click:

public void buyClick(View view) {
    mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
            mPurchaseFinishedListener, "");
}

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
        if (result.isFailure()) {
            // Handle error
            return;
        } else if (purchase.getSku().equals(ITEM_SKU)) {
            // consumeItem();
            // buyButton.setEnabled(false);
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);
        }

    }
};

The listener:

IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
    public void onQueryInventoryFinished(IabResult result,
            Inventory inventory) {

        if (result.isFailure()) {
            Toast.makeText(getApplicationContext(),
                    "Query Inventory Error!", Toast.LENGTH_SHORT).show();
            // Handle failure
        } else {
            Toast.makeText(getApplicationContext(),
                    "Query Inventory Success!", Toast.LENGTH_SHORT).show();
            // mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),
            // mConsumeFinishedListener);
            // if (inventory.hasPurchase(ITEM_SKU)) {
            // clickButton.setEnabled(true);
            // }
            Purchase item = inventory.getPurchase(ITEM_SKU);
            if (item != null) {
                clickButton.setEnabled(true);
            } else {
                Toast.makeText(getApplicationContext(),
                        "This item was not buy yet!", Toast.LENGTH_SHORT)
                        .show();
            }
        }
    }
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
    public void onConsumeFinished(Purchase purchase, IabResult result) {

        if (result.isSuccess()) {
            Toast.makeText(getApplicationContext(), "Consume done!",
                    Toast.LENGTH_SHORT).show();
            clickButton.setEnabled(true);
        } else {
            Toast.makeText(getApplicationContext(), "Consume Error!",
                    Toast.LENGTH_SHORT).show();
            // handle error
        }
    }
};

When first click on buy button, it's show the payment dialog, after make payment success, the clickButton was enable.

But when I click on the buyButton at the second times, it's go to inventory but the inventory.getPurchase(ITEM_SKU) always return null.

Any idea?

Thank you!

Maulik
  • 3,316
  • 20
  • 31
Han Tran
  • 2,073
  • 4
  • 22
  • 37
  • According to your question I think you are trying to purchase product for one time , am I right? If yes then you don't need to call consumeFinish handler for the single time purchase. – Maulik Oct 22 '13 at 09:36
  • just comment your code from onIabFinishListner "mHelper.consumeAsync(purchase, mConsumeFinishedListener);" for more information :http://stackoverflow.com/questions/19195864/android-inapp-billing-error-response-7item-already-owned/19218084#19218084 and try to purchase again and let me know it will solved or not. – Maulik Oct 22 '13 at 10:30
  • @Maulik I try to let user purchase item only once times. If user remove application and install again, I'll check if user already purchase that item then user don't need to purchase again. – Han Tran Oct 22 '13 at 10:42
  • have you tried above suggestion, 2nd comment? I have explain in the given link that why we have to call consume Async for the multiple time purchase, in your case it doesn't need to call. So just remove consumeAsync() listener from onIabPurchaseFinishlistener. – Maulik Oct 22 '13 at 10:59
  • @Maulik I will try and feedback to you later but look like it's right :-) – Han Tran Oct 22 '13 at 11:18

1 Answers1

9

just comment or remove your code from OnIabPurchaseFinishedListener "mHelper.consumeAsync(purchase, mConsumeFinishedListener);"

If you prefer Android default Trivial demo then go for the premium product purchase for the single time product purchase.

OnIabPurchaseFinishedListener()

// 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 (result.isFailure()) {
                complain("Error purchasing: " + result);
                // setWaitScreen(false);
                return;
            }
            if (!verifyDeveloperPayload(purchase)) {
                complain("Error purchasing. Authenticity verification failed.");
                // setWaitScreen(false);
                return;
            }

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


                if (purchase.getSku().equals(SKU_PREMIUM)) {
                          // bought the premium upgrade! 
                          Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
                  alert("Thank you for upgrading to premium!");
                    }

        }
    };  

Explaination why it gives null data :

Keep it mind that Google will store data from their side only when you are trying to purchase one time purchase product. But Whenever you purchased consumable item google play store will not be managed it's product purchased detail and other things in the Google play console. That's why we have to call consumeAsync() method. when we purchased item, Google play store keep record item has been purchased for the one time and allow you to purchased second time.

for more information : android: Inapp billing: Error response: 7:Item Already Owned

But, Here you are trying to purchase product as a single time purchase so you must not need to call consumeAsync() method in onIabPurchasedFinishListener.

Hope it will solve your problem.

Community
  • 1
  • 1
Maulik
  • 3,316
  • 20
  • 31