I could manage in my code to perform an in-app-billing. However, if I install the app, and redo the purchase, it does purchase again.
Where is the problem?
Here is the code:
case R.id.action_disable_ads:
try {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener);
} catch (IabHelper.IabAsyncInProgressException e) {
//e.printStackTrace();
}
return true;
}
return super.onOptionsItemSelected(item);
}
//functions special for in App Billing
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data)
{
if (!mHelper.handleActivityResult(requestCode,
resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
}
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);
}
}
};
public void consumeItem() {
try {
mHelper.queryInventoryAsync(mReceivedInventoryListener);
} catch (IabHelper.IabAsyncInProgressException e) {
//e.printStackTrace();
}
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// Handle failure
} else {
try {
mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU),
mConsumeFinishedListener);
} catch (IabHelper.IabAsyncInProgressException e) {
//e.printStackTrace();
}
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener =
new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase,
IabResult result) {
if (result.isSuccess()) {
//first save purchase state
SharedPreferences settings = getPreferences(0);
SharedPreferences.Editor settingsEditor = settings.edit();
settingsEditor.putString("adfree", "purchased");
settingsEditor.apply();
//then, hide the disable ads button
MenuItem disableAds = mainMenu.findItem(R.id.action_disable_ads);
disableAds.setVisible(false);
//then display a message that the transaction is successful
Toast.makeText(getApplicationContext(), "AdFree bundle purchased successfully!", Toast.LENGTH_SHORT).show();
//then change the state of ad-free bundle for current session:
adFreeBundle = "purchased";
//then disable ads
interstitialAd = null;
mAdView.setVisibility(View.GONE);
} else {
//display an error message that the transaction was not successful
AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());
builder.setTitle("TRANSACTION FAILED!");
builder.setMessage("Unfortunately, the transaction was unsuccessful!");
builder.setPositiveButton("CLOSE", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// Do nothing but close the dialog
dialog.dismiss();
}
});
final AlertDialog alert = builder.create();
alert.setOnShowListener(new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface arg0) {
alert.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.parseColor("#000000"));
}
});
alert.show();
}
}
};
@Override
public void onDestroy() {
super.onDestroy();
if (mHelper != null) try {
mHelper.dispose();
} catch (IabHelper.IabAsyncInProgressException e) {
//e.printStackTrace();
}
mHelper = null;
}
The process of in-app-billing functioned just fine. However, I would be happy to try to get the purchased item upon reinstalling the app.
This is because you are consuming the purchase, and setting a flag in sharedPreferences.
Don't do this anyone can change the sharedPreferences using the right tools.
When you uninstall your app your sharedPreferences will reset and you will lose your 'purchase'.
Because you consume the item, in the 2nd try your inventory won't have the right SKU available, this is why you are prompt to buy again.
If you make the buy button always visible you will be asked to pay every click.
To fix this
Don't consume the item, and the most important thing don't set any flag in sharedPreferences. this also apply's to sql databases.
Consuming is not meant to be used in a non-consumable item, this is your case since you are charging the user to remove the ads, if you try to consume this your users won't be very happy
When your app starts check your inventory if your inventory has the right SKU then give the user the product.
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
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.");
try {
mHelper.queryInventoryAsync(new IabHelper.QueryInventoryFinishedListener() {
@Override
public void onQueryInventoryFinished(IabResult result, Inventory inv) {
handleInventory(result, inv);
}
});
} catch (IabHelper.IabAsyncInProgressException e) {
complain("Error querying inventory. Another async operation in progress.");
e.printStackTrace();
}
}
});
public void handleInventory(IabResult result, Inventory inventory) {
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
return;
}
Log.d(TAG, "Query inventory was successful.");
Purchase premiumPurchase = inventory.getPurchase(YOUR SKU);
//verify Developer Payload here, it's recommended but not mandatory.
//mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
mIsPremium = premiumPurchase != null;
if (mIsPremium) {
//Enable feature
}else{
//Disable feature
}
}