22

If I send a purchase intent via the standard

String mySku = "android.test.purchased";

mHelper.launchPurchaseFlow(this, mySku, 10001, mPurchaseFinishedListener);

I am able to purchase the item and it will store and I can query the item and that works fine too. The only thing that doesn't work is is the PurchaseFinishedListener. I've got it coded pretty much identical to the sample app however it doesn't seem to get called at all.

12-12 01:40:47.248: D/IabHelper(23502): Calling getPurchases with continuation token: null
12-12 01:40:50.116: D/IabHelper(23502): Starting async operation: launchPurchaseFlow

These are the last two methods that get called and after that when I finish the purchase it doesn't call the purchasefinishedlistener

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new OnIabPurchaseFinishedListener() {

    @Override
    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 (purchase.getSku().equals(mySku)) {
            Log.d(TAG, "mySku is being consumed.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);
        }
        Log.d(TAG, "Purchase successful.");
        new AsyncQuestionsActivity().doInBackground();
    }
};

Nothing from the log to the end works. Is there anything that I'm just somehow missing?

AndroidPenguin
  • 3,445
  • 2
  • 21
  • 42

4 Answers4

50

I found out how to fix it. Implement handleActivityResult in onActivityResult. It's needed to create a bridge between the listener and the launched purchase flow.

Given below is the code I used:

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

        Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + ","
                + data);

        // Pass on the activity result to the helper for handling
        if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        } else {
            Log.d(TAG, "onActivityResult handled by IABUtil.");
        }
    }
binW
  • 13,220
  • 11
  • 56
  • 69
AndroidPenguin
  • 3,445
  • 2
  • 21
  • 42
  • can you please elaborate a little with some code may be? Thanks in advance. – binW Apr 14 '13 at 12:22
  • How is `mHelper`initialized in this case? – Mr Auni Jun 10 '13 at 13:35
  • 5
    It's mildly insane that this isn't better documented in the Android docs, arrgh – Alfie Hanssen Aug 02 '13 at 19:34
  • 9
    @AndroidPenguin do you really need to call the supers onActivityResult() two times? – nyaray Aug 16 '13 at 10:01
  • In my case, the listener's reference is getting lost when I rotate the device. REALLY IRRITATING. – joepetrakovich Sep 27 '13 at 19:57
  • Make the listener a static variable @some_developer – AndroidPenguin Sep 27 '13 at 20:43
  • @AndroidPenguin but then everything inside the listener's onIabPurchaseFinished method has to be static, and that doesn't seem right. – joepetrakovich Sep 27 '13 at 20:56
  • @AndroidPenguin actually what really is happening is that when I rotate the device WHILE A PURCHASE DIALOG IS OPEN, and then close the dialog, the listener isn't getting called because the IabHelper was recreated and no longer has the same mRequestCode that is was called with, so the handleActivityResult method doesn't get to the part where it fires the listener's callback. – joepetrakovich Sep 27 '13 at 21:00
  • @some_developer is your IabHelper (e.g. mHelper) a static variable? that's how I fixed mine... – AndroidPenguin Oct 05 '13 at 23:48
  • @AndroidPenguin no it's not. But I figured out a solution. – joepetrakovich Oct 07 '13 at 15:39
  • My code is working fine without adding this code, I just followed the sample on android website. I am developing for Android version 4.0.3 – zeeshan Nov 13 '13 at 17:09
  • This code sometimes calls `super.onActivityResult()` twice. Isn't that problematic? – Gak2 Apr 14 '14 at 18:18
  • 1
    Important: I tried putting the above snippet into the Fragment from which the purchase was initiated. This caused the callback to work for purchases that *failed* but oddly, not for successful purchases. Took me forever to discover that the OnActivityResult() snippet had to be in my actual main Activity, *not* in the Fragment. (Any idea why, anyone?) – RobP Jun 03 '14 at 07:01
  • @RobP I had to move the iabHelper.dispose() function to onDestroy of the activity too. Perhaps, iabHelper was disposed too early when using fragments. The reason why it would work for failures may be that you didn't have to traverse as far through the code to get to a failure, so it wasn't disposed. Have you figured this out yet? – ginsengtang May 22 '16 at 20:02
  • Why call super.onActivityResult() twice? – WiMa Apr 08 '17 at 08:14
5

AndroidPenguin, I'm running into the same issue as you, but I have the activityresult correctly set and yet my purchasefinishedlistener does not execute.

Here is my onActivityResult

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (SettingsManager.getBooleanSetting(rootId, "inapppurchase", false)){
        Log.d(TAG, "take care of activity result with billing helper");
        if (!mBillingService.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.");
        }
    }
    else
        super.onActivityResult(requestCode, resultCode, data);
}
Hartok
  • 2,147
  • 20
  • 37
kevinl
  • 4,194
  • 6
  • 37
  • 55
  • 2
    Did you able to resolve the issue ? I'm having a same issue. in which mHelper.launchPurchaseFlow is not recognized. – Arsalan Mar 13 '13 at 10:00
  • 2
    yes I did resolve the issue. What happened was that I was implementing onActivityResult in the wrong class. I'm using fragments as well as activities and it seems that my parent class ACTIVITY needed to implement onActivityResult but not the fragment. For example: sampleFragment was called from sampleActivity. You must implement onActivityResult in sampleActivity. – kevinl Mar 14 '13 at 14:27
  • I had the same issue as @kevinl more or less, and it took me forever to find it. Adding the OnActivityResult() to the Fragment worked some of the time, e.g. some *failed* purchases, but not for successful ones. Putting OnActivityResult in the "parent" Activity fixes the issue. (Would have helped a lot if you edited your ANSWER, and not left this important tidbit in a comment. If you do that I'll upvote it!) – RobP Jun 03 '14 at 07:09
1

In my case, it is working try like this, wait until that google play dialog close itself.Then, the listener will get called

Sreedhu Madhu
  • 2,480
  • 2
  • 30
  • 40
-1

For those of you who had the same issue I was experiencing...

I just made my member variable IabHelper static, and that fixed the issue.

I already had added AndroidPenguin's code, and was still getting crashes from a null IabHelper, after I had purchased an item(so onActivityResult never had a chance to call handleActivityResult because mHelper was null).

wizurd
  • 3,541
  • 3
  • 33
  • 50