I'm trying to implement the inApp billing service with IabHelper. I manage to go through the full purchase process without problems.
//-----------------------------------------------
public void billingServiceLaunchPurchase(String item) {
//-----------------------------------------------
if (isNetworkAvailableSync(getBaseContext())) {
currBuyItem=item;
billingConsummeType=1;
mHelper.launchPurchaseFlow(BaseActivity.this, item, 10001, mPurchaseFinishedListener, "");
}
else {
onBillingServiceFailed();
}
}
//-----------------------------------------------
mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
//-----------------------------------------------
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure()) {
// Handle error
onBillingServiceFailed();
return;
}
else if (purchase.getSku().equals(currBuyItem)) {
billingServiceConsumeItem();
}
}
};
#Override
//-----------------------------------------------------------------------
protected void onActivityResult(int requestCode, int resultCode, Intent data)
//-----------------------------------------------------------------------
{
if (billingServiceConnected) {
if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
}
else {
// onActivityResult handled by IABUtil.
}
}
else
super.onActivityResult(requestCode, resultCode, data);
}
However, I cannot detect the event when the user launches the purchase but then press the backspace on the Google confirmation screen with the button "BUY" to interrupt it.
It neither triggers a failure on onIabPurchaseFinished nor it triggers onActivityResult so my application stays in an intermediary status.
Please help me to solve my problem.
According to what I have understood your question, you are searching for purchase cancel event in app billing.
You can trigger this via onActivityResult() method.Put below code in onActivityResult() method. There is simple RESEULT_CANCEL type that shows you user has been cancel purchasing.
if (mHelper == null)
return;
if (requestCode == 10001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
Log.d("INAPP_PURCHASE_DATA", ">>>" + purchaseData);
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
Log.d("INAPP_DATA_SIGNATURE", ">>>" + dataSignature);
String continuationToken = data
.getStringExtra("INAPP_CONTINUATION_TOKEN");
Log.d("INAPP_CONTINUATION_TOKEN", ">>>" + continuationToken);
if (resultCode == RESULT_OK) {
try {
Log.d("purchaseData", ">>>"+purchaseData);
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku
+ ". Excellent choice, adventurer!");
} catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
} else if (resultCode == RESULT_CANCELED) {
Toast.makeText(AppMainTest.this,
"Sorry, you have canceled purchase Subscription.",
Toast.LENGTH_SHORT).show();
} else if (resultCode == IabHelper.BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED) {
Toast.makeText(AppMainTest.this, "Item already owned",
Toast.LENGTH_SHORT).show();
}
}
}
or
you can also handle manually by using your business logic. check if
user cancel purchase product then put flag user has been purchased or
not if not then call launchPurchaseFlow() method again.
EDIT
onDestroy() method
#Override
public void onDestroy() {
super.onDestroy();
// very important:
Log.d(TAG, "Destroying helper.");
if (mHelper != null)
mHelper.dispose();
mHelper = null;
}
if you have button then you can directly call launchPurchaseFlow()
method into onClick event so that every time your mHelper created as
new purchase.
or
if you are using it in onCreate method and you haven't any button
click event to purchase product then you have to give value as null
according to my knowledge.
Hope it will solve your problem.
When user press BACK or press outside the dialog, the purchase flow is still in process and if user press PURCHASE button again, there will be an exception "Can't start async operation because another async operation is in progress".
To fix this, I had manually create a flag to know if there is a purchase flow in progress. And since IABHelper don't provide a way to dispose a purchase flow, I have to dispose mHelper and recall initBilling()
boolean onPurchaseFlow = false;
public void purchaseItem() {
if (!onPurchaseFlow) {
mHelper.launchPurchaseFlow(mActivity, SKU_PREMIUM, RC_REQUEST, mPurchaseFinishedListener, "");
onPurchaseFlow = true;
} else {
//dispose mHelper
if (mHelper != null) {
mHelper.dispose();
mHelper = null;
}
initBilling(mActivity); // restart IABHelper, a code snippet will fire launchPurchaseFlow when onPurchaseFlow is true
}
}
The other important part is call launchPurchaseFlow in onQueryInventoryFinished() to ensure that it is called (in the second request of user) when all the init operation has completed:
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
// YOUR CODE HERE
if (onPurchaseFlow == true) {
mHelper.launchPurchaseFlow(mActivity, SKU_PREMIUM, RC_REQUEST, mPurchaseFinishedListener, "");
}
}
Remember to reset the flag onPurchaseFlow = false when finish in onIabPurchaseFinished()
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_PREMIUM)) {
// bought the premium upgrade!
// YOUR CODE HERE
onPurchaseFlow = false;
}
}
You can access the result code through IabResult class, and compare it with the different result codes in IabHelper class, and use it in your OnIabPurchaseFinishedListener:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure()) {
if (result.getResponse() == IabHelper.BILLING_RESPONSE_RESULT_USER_CANCELED || result.getResponse() == IabHelper.IABHELPER_USER_CANCELLED){
// user cancelled purchase
} else {
// any oder reasult
}
return;
}
else if (purchase.getSku().equals(SKU_SPIRIT_LEVEL)) {
// no error, purchase succeeded
}
}
};
you can detect the back press overriding by this method
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
//do what you want to avoid going back while during transaction
Log.d("bak button pressed", "ture");
}
return super.onKeyDown(keyCode, event);
}
even check this out, it might help you
Check if back key was pressed in android?
Inside IabHelper there's a method called handleActivityResult(...).
If you override onActivityResult (Fragment or Activity) and call that method inside (call it with the same parameters). In this way, the helper manage all the callbacks and can redo the purchase flow without launching any exceptions.
Related
I am new to in-app purchase system. I just watched some tutorials, then implemented in-app purchase. However, when my in-app purchase was successful, it did not run my code. Does it have to run the following code?:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString(inappid);
Toast.makeText(
MainActivity.this,
"You have bought the " + sku
+ ". Excellent choice,adventurer!",
Toast.LENGTH_LONG).show();
writeInApp("1");
playGroundMain.bonus_pop_up(R.drawable.rich_big, "\"VIP Монстр\"");
playGroundMain.reWriteBonus("1", 6);
} catch (JSONException e) {
System.out.println("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
I've made a fair few apps with the payment system, you should take a look at this listener
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d(TAG, "Consumption finished. JSON: " + purchase.getOriginalJson() + ", signature: " + purchase.getSignature());
if (mHelper == null) return;
if (result.isSuccess())
{
Log.i(TAG, "BOUGHT THE ITEM :-)")
}
else
{
Log.e(TAG, "Error while consuming: " + result);
}
Log.d(TAG, "End consumption flow.");
}
};
you could add this listener in the consumeAsync function of the IabHelper like so:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener()
{
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (purchase.getSku().equals(SKU_21500))
{
// bought 21500 credits
Log.d(TAG, "Purchase is 21500 credits. Starting credits consumption.");
try
{
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
}
catch (IabHelper.IabAsyncInProgressException e)
{
Log.d(TAG, "Error consuming 21500 credits. Another async operation in progress.");
return;
}
}
}
}
And then you can put the "mPurchaseFinishedListener" in the "launchPurchaseFlow " function as so:
mHelper.launchPurchaseFlow(activity, item, REQUEST_CODE, mPurchaseFinishedListener);
REQUEST_CODE being 10001
Hope this helps!
If you are trying to do a non-consumable inapp purchase the code is fine.
When doing test purchases sometimes the onActivityResult() does not gets called. In a real purchase this may not happen.
To handle the purchase in that case you have to check result code == user already owns this item //resultCode 7, so that the user will not have to pay again in a situation like this.
I am trying to remove AdMob ads in my app upon an in-app purchase. I already have the code to hide and disable the ads working. I also have in-app billing implemented. I just need to find a way to keep the ads hidden and disabled if the user has made a purchase.
I have a boolean stored in SharedPreferences, which, upon a successful in-app purchase, should permanently remove the ads in the app. This works, but when the app is closed and reopened, the ads are back and you cannot perform the purchase again.
In onCreate() method:
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
} else {
}
}
});
prefs = this.getSharedPreferences("com.wsandhu.conjugation", Context.MODE_PRIVATE);
if (adFree) {
prefs.edit().putBoolean("adFree", true).commit();
} else {
adFree = prefs.getBoolean("adFree", false);
}
In-App Billing implementation:
/* 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)) {
// Sets purchased boolean to true
adFree = true;
// Restart app
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
}
}
};
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// Handle failure
} else {
Purchase purchase = inventory.getPurchase(ITEM_SKU);
if (purchase != null) {
} else {
}
}
}
};
public void buyFullVersion() {
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001,
mPurchaseFinishedListener, "mypurchasetoken");
}
I don't really know what I'm doing wrong... I've uploaded the app to Google Play alpha testing more than ten times now and I'm getting a bit frustrated each time I wait two hours and it doesn't work. :P Help?
Here:
adFree = true;
Causing issue when user opening app again after closing adFree variable value getting reset to default.
Do it as by updating status in SharedPreferences when purchase is successful :
...
}else if (purchase.getSku().equals(ITEM_SKU)) {
//save value in SharedPreferences here
prefs.edit().putBoolean("adFree", true).commit();
}
and in onCreate method check for adFree as:
prefs = this.getSharedPreferences("com.wsandhu.conjugation",Context.MODE_PRIVATE);
if(prefs.contains("adFree")){
if(prefs.getBoolean("adFree", false)){
// disable ads here
}else{
// enable ads here
}
}else{
// enable ads
}
i have almost finished my first app. I have my in-app purchasing working, but it turns out i have a problem with consuming the purchases, since it should be possible to buy the item endless times. I think i have edited the code to consume the purchased item correctly now, I will provide the code so you can correct me if I'm wrong. But even though this code might be correct now, I can't purchase the product on my test device again, since it wasn't consumed when bought in the first place. How can i consume the product now? Here is my updated code.
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()) {
Log.d("Unlock", "Error purchasing: " + result);
return;
} else if (purchase.getSku().equals(SKU_HINTS)) {
consumeItem();
}
}
};
public void consumeItem() {
mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// Handle failure
} else {
mHelper.consumeAsync(inventory.getPurchase(SKU_HINTS),
mConsumeFinishedListener);
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
if (result.isSuccess()) {
add_hints();
purchase1.setText("Purchase complete");
} else {
// handle error
}
}
};
public void onClick(View v) {
case R.id.bUnlockHints:
mHelper.launchPurchaseFlow(this, SKU_HINTS, 10001,
mPurchaseFinishedListener, "");
break;
}
I figured out the answer. I had to change the startSetup method so it queries the inventory right away. Here is my new code.
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// Handle failure
}
// This is the updated part
Purchase hintPurchase = inventory.getPurchase(SKU_HINTS);
if (hintPurchase != null) {
mHelper.consumeAsync(inventory.getPurchase(SKU_HINTS),
mConsumeFinishedListener);
}
}
};
Here I check if the hints have been purchased before consuming it. Otherwise i would receive an error.
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d("Ultimate Quiz",
"Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
// Here I run the queryInventory to check right away if the product has been bought, and consume it if it has.
mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
});
I am learning to implement an in-app billing for my app such that people can for example, donate $ when press the donate button.
The user is allowed to donate more than one time, i.e. the purchase is consumable.
The codes below are sourced from the TrivalDrive sample and some tutorials from the web:
Code:
IabHelper mHelper;
static final String ITEM_SKU = "android.test.purchased";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_in_app_billing);
buy10Button = (Button) findViewById(R.id.buy10Button);
buy15Button = (Button) findViewById(R.id.buy15Button);
buy20Button = (Button) findViewById(R.id.buy20Button);
String base64EncodedPublicKey = "keykeykey";
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);
return;
}
if (mHelper == null)
{
return;
}
Log.d(TAG, "In-app Billing is set up OK");
}
});
}
public void buy10Click(View view)
{
mHelper.launchPurchaseFlow(this, ITEM_SKU, 10001, mPurchaseFinishedListener, "");
}
public void buy15Click(View view)
{
}
public void buy20Click(View view)
{
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (mHelper == null) return;
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 (mHelper == null) return;
if (result.isFailure())
{
// Handle error
return;
}
else if ((purchase.getSku().equals(ITEM_SKU)))
{
consumeItem();
}
}
};
public void consumeItem()
{
mHelper.queryInventoryAsync(mReceivedInventoryListener);
}
IabHelper.QueryInventoryFinishedListener mReceivedInventoryListener = new IabHelper.QueryInventoryFinishedListener()
{
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
if (mHelper == null) return;
if (result.isFailure())
{
// Handle failure
}
else
{
mHelper.consumeAsync(inventory.getPurchase(ITEM_SKU), mConsumeFinishedListener);
}
}
};
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener()
{
public void onConsumeFinished(Purchase purchase, IabResult result)
{
if (mHelper == null) return;
if (result.isSuccess())
{
Toast.makeText(InAppBillingActivity.this, "Thank you for your donation!!", Toast.LENGTH_LONG).show();
}
else
{
// handle error
}
}
};
Question:
Yet I keep on receiving E/IabHelper(13392): In-app billing error: Unable to buy item, Error response: 7:Item Already Owned error and that the payment dialog of the Google Play just does not popup.
I have researched and found out many similar situations, some suggested to wait for a few minute and then the purchase will be reset by itself, but I have waited for almost an hour but it still sucks.
I have also found that someone suggest to change the IabResult public boolean isSuccess() { return mResponse == IabHelper.BILLING_RESPONSE_RESULT_OK; } to return also the BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED as isSuccess = true, yet i dont know how to amend such...
How could the problem be fixed? Thanks!!
You purchased "android.test.purchased" but did not consume it. However, if you forgot to consume it immediately, it is not easy to consume it again. We can wait for 14 days. The fake purchase will be cleared automatically. But it is not acceptable.
I spent a lot of time finding the solution:
Add this line to get debug info.
_iabHelper.enableDebugLogging(true, "TAG");
Run the app. In LogCat, you will see a json string like
{"packageName":"com.example","orderId":"transactionId.android.test.purchased","productId":"android.test.purchased","developerPayload":"123","purchaseTime":0,"purchaseState":0,"purchaseToken":"inapp:com.example:android.test.purchased"}
Consume it manually (Replace THAT_JSON_STRING with your json string)
Purchase purchase;
try {
purchase = new Purchase("inapp", THAT_JSON_STRING, "");
_iabHelper.consumeAsync(purchase, new OnConsumeFinishedListener() {
#Override
public void onConsumeFinished(Purchase purchase, IabResult result) {
Log.d("TAG", "Result: " + result);
}
});
} catch (JSONException e) {
e.printStackTrace();
}
_iabHelper is mHelper.
Check my below code here:
I don't understand in your code why have you used query inventory in purchase finish listener. ConsumeAsync() method should be call while you getting the sku same as your requested sku.
// 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);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_GAS)) {
// remove query inventory method from here and put consumeAsync() directly
mHelper.consumeAsync(purchase, mConsumeFinishedListener);
}
}
};
startSetup method
// you have forgot to call query inventory method in startSetup method.
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;
}
// Hooray, 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);
}
});
QueryInventoryFinishedListener
And also check if condition purchase is same as you are requested is
not equals to null and developer payload is also same in your query
inventory finish listener.
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)){
//code
}
// 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.");
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().
*/
// // Check for gas delivery -- if we own gas, we should fill up the
// tank immediately
Purchase gasPurchase = inventory.getPurchase(SKU_GAS);
if (gasPurchase != null && verifyDeveloperPayload(gasPurchase)) {
Log.d(TAG, "We have gas. Consuming it.");
mHelper.consumeAsync(inventory.getPurchase(SKU_GAS),
mConsumeFinishedListener);
return;
}
}
};
Explaination why it happends:
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.
Hope it will solve your problem.
You can use Google Play "FINANCIAL REPORTS"->"Visit your merchant account for more details"->"Orders" to View and Cancel any order to "consume it".
Then you need to restart your device. =)
I managed to "consume the purchase" simply by restarting the device.
I'm using: implementation 'com.android.billingclient:billing:2.0.0' and had the same error on purchase process.
the point is: before of launching the purchase we should consume the pending purchases.
please see the code snippet below:
List<String> skuList = new ArrayList();
skuList.add(THE_IAP_ID);
BillingClient.Builder billingClientBuilder = BillingClient.newBuilder(context).setListener(new PurchasesUpdatedListener() {
#Override
public void onPurchasesUpdated(BillingResult billingResult, #Nullable List<Purchase> purchases) {
// here we have to check the result ...
});
billingClientBuilder.enablePendingPurchases();
billingClient = billingClientBuilder.build();
billingClient.startConnection(new BillingClientStateListener() {
#Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
// The BillingClient is ready - query purchases.
Purchase.PurchasesResult pr = billingClient.queryPurchases(BillingClient.SkuType.INAPP);
List<Purchase> pList = pr.getPurchasesList();
for (Purchase iitem : pList) {
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(iitem.getPurchaseToken())
.build();
billingClient.consumeAsync(consumeParams, consumeResponseListener);
}
// process the purchase
} else {
// cancelled or s.e.
...
}
}
Best Regards, Have you fun :)
I have been struggling with this for over a week. I am working on subscriptions on the android use their In-App Billing Version 3 I built the code and have it running for purchase but as it was done last year this version did not support subscriptions and since I put this together from the example I don't have code to build the code to use subscriptions.
Here is the code I have in place for purchases and as I understand it I need to alter these to work with subscriptions instead of purchases plus add the code for determining if a subscription is valid on the google server. I do not see code for that right now.
String base64EncodedPublicKey = "MI...QAB";
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set
// this to false).
mHelper.enableDebugLogging(false);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
// complain("1 "+"Problem setting up in-app billing: " +
// result);
return;
}
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
// Listener that's called when we finish querying the items we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
// ///Log.d(TAG, "Query inventory finished.");
if (result.isFailure()) {
// complain("2 "+"Failed to query inventory: " + result);
return;
}
// ///Log.d(TAG, "Query inventory was successful.");
// place code here to proceess purchase without reaccessing database
if (inventory.hasPurchase(appSKU)) {
// ///Log.i("Purchase","purchase consumed here");
//mHelper.consumeAsync(inventory.getPurchase(appSKU),mConsumeFinishedListener);
return;
}
}
};
public void order(String appSKU) {
mHelper.launchPurchaseFlow(this, appSKU, RC_REQUEST,
mPurchaseFinishedListener);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + ","
// + data);
// 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...
super.onActivityResult(requestCode, resultCode, data);
} else {
// ///Log.d(TAG, "onActivityResult handled by IABUtil.");
}
}
// 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(purchase == null) {
;
}else {
String tester1 = purchase.toString();
// ///Log.d(TAG, "Purchase successful.");
// mHelper.consumeAsync(purchase, mConsumeFinishedListener);
// myCallServer(udid, calltype, data, OrderID, ProductId, PurchaseToken) {
Bundle myBundle = new Bundle();
myBundle.putString("AppTitle", AppTitle);
Intent myIntent = new Intent(getBaseContext(),
IntroALevActivity.class);
myIntent.putExtras(myBundle);
startActivity(myIntent);
}
}
};
// Called when consumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
public void onConsumeFinished(Purchase purchase, IabResult result) {
// ///Log.d(TAG, "Consumption finished. Purchase: " + purchase +
// ", result: " + result);
// We know this is the "gas" sku because it's the only one we
// consume,
// so we don't check which sku was consumed. If you have more than
// one
// sku, you probably should check...
if (result.isSuccess()) {
// successfully consumed, so we apply the effects of the item in
// our
// game world's logic, which in our case means filling the gas
// tank a bit
alert("You made a purchase");
} else {
;
}
}
};
I have looked online but I have only found broken pieces of code to help me determine what the exact method code would be to check for existing subscriptions. If some one could look at my code and supply the method I am missing it would be great. Google examples have usually been good but since subscriptions have just been added to V3 as of Feb 15th there are not a lot of coding examples to build from.
I am struggling so if you have any questions or need additional information just let me know and I will do the best I can to supply it.
Thanks to the stackoverflow members
Even though I'm not using subscriptions in my implementation you can check that in your IabHelper.QueryInventoryFinishedListener mGotInventoryListener function. So instead of this:
// ///Log.d(TAG, "Query inventory was successful.");
// place code here to proceess purchase without reaccessing database
if (inventory.hasPurchase(appSKU)) {
// ///Log.i("Purchase","purchase consumed here");
//mHelper.consumeAsync(inventory.getPurchase(appSKU),mConsumeFinishedListener);
return;
}
Use this:
Purchase haspurchase = inventory.getPurchase(appSKU);
if (haspurchase = null) {
// do something since there wasn't a purchase
}
else {
// do something if you have the purchase
}
To work with in app subscription i think you will gave to call "launchSubscriptionPurchaseFlow()" method on IabHelper instance you create.
mHelper.launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData);
OR
mHelper.launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode,
OnIabPurchaseFinishedListener listener, String extraData);
Where itemType = IabHelper.ITEM_TYPE_SUBS