Android In-App Billing v3: "Unable to complete operation: queryInventory"

I have an In-App Billing setup for the first time using the new v3 API. It works correctly on my devices, but I have received many error reports from other users.

One of them:

java.lang.IllegalStateException: IAB helper is not set up. Can't perform operation: queryInventory at my.package.util.iab.IabHelper.checkSetupDone(IabHelper.java:673) at my.package.util.iab.IabHelper.queryInventory(IabHelper.java:462) at my.package.util.iab.IabHelper$2.run(IabHelper.java:521) at java.lang.Thread.run(Thread.java:1019) 

And one more:

 java.lang.NullPointerException at my.package.activities.MainActivity$4.onIabSetupFinished(MainActivity.java:159) at my.package.util.iab.IabHelper$1.onServiceConnected(IabHelper.java:242) 

My activity implementation follows the example of Google code (all reference classes are intact from the example):

 IabHelper mHelper; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... mHelper = new IabHelper(this, IAB_PUBLIC_KEY); mHelper.enableDebugLogging(true); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { if (!result.isSuccess()) { // Oh noes, there was a problem. return; } // Hooray, IAB is fully set up. Now, let get an inventory of // stuff we own. mHelper.queryInventoryAsync(mGotInventoryListener); //***(1)*** } }); } // Listener that called when we finish querying the items we own IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { if (!result.isFailure()) { if (inventory.hasPurchase(SoundsGlobals.IAB_SKU_PREMIUM)){ //we are premium, do things } } else{ //oops } } }; @Override protected void onDestroy() { if (mHelper != null) { mHelper.dispose(); mHelper = null; } super.onDestroy(); } 

I assume both errors come from a line labeled as ***(1)***

What is the cause of these errors? If I call queryInventoryAsync only inside onIabSetupFinished , how is it possible that mHelper is null or that mHelper not configured?

Does anyone know about this solution?

+27
android in-app-billing
Dec 25
source share
11 answers

As @Martin explained, an error occurred in the Google In-App Billing example that caused this.

However, after fixing it, I still got some errors in the internal calls ( queryInventory inside the thread created in queryInventoryAsync in some rare cases that the helper is not configured). I solved this by adding an extra catch in this case:

 try { inv = queryInventory(querySkuDetails, moreSkus); } catch (IabException ex) { result = ex.getResult(); } catch(IllegalStateException ex){ //ADDED THIS CATCH result = new IabResult(BILLING_RESPONSE_RESULT_ERROR, "Helper is not setup."); } 

I also crashed on mHelper.dispose() , which I fixed in a similar way:

 try{ if (mContext != null) mContext.unbindService(mServiceConn); } catch(IllegalArgumentException ex){ //ADDED THIS CATCH //IGNORE IT - somehow, the service was already unregistered } 

Of course, instead of ignoring these errors, you can write them to ACRA without problems, for example :)

Thanks for your comments.

+18
Mar 09 '13 at 13:29
source share

There is an error in IABHelper. There is no return line in the exception handler, which means that it fails and causes hanlder to succeed - however, mSetupDone was not installed, so further API calls are not made. Add a return statement as shown below: this will still not work, but the error message will be correctly reported to your application so that you can take the appropriate action.

  catch (RemoteException e) { if (listener != null) { listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, "RemoteException while setting up in-app billing.")); } e.printStackTrace(); return; // This return line is missing } if (listener != null) { listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful.")); } 
+13
Feb 06 '13 at
source share

I believe that there are still two errors in the Android code, which explains why you still see the error. Please note that the call stack is in an offline stream. But the code that sets mSetupDone (IabHelper) to true is executed in the main user interface thread. Java does not guarantee that data modified by one thread will be visible to another thread due to CPU caching unless you declare a variable with the volatile keyword. Thus, it is possible that it was configured (mSetupDone == true), but the new mSetupDone value is cached in the user interface thread that is not yet visible to this thread in your call stack. So the thread still sees mSetupDone == false.

I tried to fix this by declaring mSetupDone with mutable, as well as any other non-final IabHelper field, to be safe.

Now another problem is the .dispose () function. It does not stop current threads. This means that it can set mSetupDone to false while one of the worker threads is running. If you look at queryInventoryAsync (), you will see that it checks that mSetupDone is true. And, based on your call stack, that passed. Then it crashed later with mSetupDone == false. The only way that can happen is to call dispose () while your thread is in flight. The fix is ​​that dispose () should signal threads to just silently help out, and not continue and throw errors when it sees mSetupDone == false. It also prevents another problem with IabHelper when installed instances invoke listener callbacks even after they are deleted! This is a little difficult to explain line by line here, but we hope in this way we get you to point in the right direction.

+9
May 25 '13 at 14:09
source share

I found out! This is about the version of the Google Play Store app. Billing V3 for applications requires 3.9.16 or higher ( http://developer.android.com/google/play/billing/versions.html ). I used an older version and I got this error, now on 4.4.21 this is normal!

+6
Nov 06 '13 at 17:11
source share

Make sure you use the IabHelper.han.handleActivityResult(requestCode, resultCode, data) method in your onActivityResult actions.

  @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // Pass on the activity result to the helper for handling if (!mIabHelper.handleActivityResult(requestCode, resultCode, data)) { // not handled, so handle it ourselves (here where you'd // perform any handling of activity results not related to in-app // billing... super.onActivityResult(requestCode, resultCode, data); } else { Log.i(TAG, "onActivityResult handled by IABUtil."); } } 
+2
Jan 02 '13 at 7:36
source share

I get this EXACT same error with almost the same code.

It seems to only happen on some phones (in fact it is almost exclusively Acer Iconia Tablet in recent bug reports!) - and I am processing onActivityResult ...

Google V3 Billing Sample has a number of errors that ANR / FC can cause. I suspect this is just one more thing (crappy code and crappy documents are becoming a trademark of Google - unfortunately).

My assumption - for now - we need to allow either mHelper or mGotInventoryListener to be null and just disable In-App Billing in this case (as if result.isSuccess () was false, basically)

ps to add - it can only be that the user has an outdated version of the Play Store - it is only auto-update if they allow him to work !?

+2
Jan 04 '13 at 12:17
source share

You can keep up to date with the inapp v3 API development at https://code.google.com/p/marketbilling/

The code is newer than the one available through the Android SDK Manager.

+1
Apr 23 '13 at 7:58
source share

In addition to @DavidM and @Ereza.

Another major issue with the IabHelpr class is the poor selection of RuntimeExcptions (IllegalStateException) metadata in several ways. Throwing RuntimeExceptions from your own code is in most cases undesirable due to the fact that they are unchecked exceptions. This is like sabotaging your own application - if not caught, these exceptions will bubble and crash your application.

The solution to this is to implement your own checked exception and change the IabHelper class to use it instead of the IllegalStateException. This will force you to handle this exception wherever it can be thrown into your code at compile time.

Here is my usual exception:

 public class MyIllegalStateException extends Exception { private static final long serialVersionUID = 1L; //Parameterless Constructor public MyIllegalStateException() {} //Constructor that accepts a message public MyIllegalStateException(String message) { super(message); } } 

Once we make changes to the IabHelper class, we can handle our checked exception in our code, where we call the class methods. For example:

 try { setUpBilling(targetActivityInstance.allData.getAll()); } catch (MyIllegalStateException ex) { ex.printStackTrace(); } 
+1
Nov 02
source share

If all of the above does not help you, try to analyze your code a bit - is your IabHelper at the time you call it?

I realized that I was doing it a little wrong, not realizing it. A simple use case is incorrect in Activity.onCreate()

 m_iabHelper = new IabHelper(this, base64EncodedPublicKey); // Declare m_iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { // Setup public void onIabSetupFinished(IabResult result) { // Setup code } } // Don't do this, will produce an error List additionalSkuList = new ArrayList(); additionalSkuList.add(SKU_MYSKU); m_iabHelper.queryInventoryAsync(true, additionalSkuList, m_queryFinishedListener); // Don't do this, will produce an error 

.

You read you with the error "IAB helper is not setup", because while the application is trying to execute m_iabHelper.queryInventoryAsync() , IabHelper has not yet been configured. Consider using these functions in onIabSetupFinished() or somewhere after calling this function (for example, outside onCreate() )

+1
Nov 11 '14 at 22:45
source share

I get the same errors. I also ran into other problems ...

Having more than one google account on a device that is disabled in the billing application on my Galaxy 7 tab. Delete one account by re-enabling it.

I saw problems with sample code for billing applications on the GT-P5110, LGL75C and GT-S5839i and others.

(I use the code in the application with ACRA installed ... so every time it crashes, I get information)

Android devices version 2.3.3 to 4.0.4.

This is very annoying.

0
Jan 11 '13 at 0:44
source share

There were a lot of problems with IABHelper.java.

Firstly, the version downloaded by the SDK manager is not updated. Use the version found here: https://code.google.com/p/marketbilling/source/detail?r=15946261ec9ae5f7c664d720f392f7787e3ee6c7 This is the most current version to publish this answer. Many problems seem to have been fixed with this version compared to the original version that comes from the SDK manager.

The only thing I had to change in this version was to add flagEndAsync(); after line 404, which fixes the IllegalStateException when two fast IAB purchases start quickly.

With this version you do not need to control using flagEndAsync(); in your files and leave this method unavailable.

0
Apr 20 '15 at 15:46
source share



All Articles