IAB helper is not set up. Can't perform operation: queryInventory

Georgi Koemdzhiev picture Georgi Koemdzhiev · Jun 24, 2015 · Viewed 13.8k times · Source

I am trying to implement in-app-billing API in my app but when I run my app it trows an exception. This is the first time that I am dealing with in-app-billing API. This is the log of the exception that I am getting:

Process: koemdzhiev.com.quickshoppinglist, PID: 10604
java.lang.RuntimeException: Unable to start activity ComponentInfo{koemdzhiev.com.quickshoppinglist/koemdzhiev.com.quickshoppinglist.ui.MainActivity}: java.lang.IllegalStateException: IAB helper is not set up. Can't perform operation: queryInventory
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2329)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2389)
        at android.app.ActivityThread.access$900(ActivityThread.java:147)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1296)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:898)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:693)
 Caused by: java.lang.IllegalStateException: IAB helper is not set up. Can't perform operation: queryInventory
        at koemdzhiev.com.quickshoppinglist.utils.IabHelper.checkSetupDone(IabHelper.java:782)
        at koemdzhiev.com.quickshoppinglist.utils.IabHelper.queryInventoryAsync(IabHelper.java:610)
        at koemdzhiev.com.quickshoppinglist.utils.IabHelper.queryInventoryAsync(IabHelper.java:639)
        at koemdzhiev.com.quickshoppinglist.ui.MainActivity.queryPurchasedItems(MainActivity.java:187)
        at koemdzhiev.com.quickshoppinglist.ui.MainActivity.onStart(MainActivity.java:193)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1220)

My code in main activity:

public class MainActivity extends AppCompatActivity {
private static final String TAG =  MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private RecyclerView mRecyclerView;
private ArrayList<String> shoppingListItems;
private SharedPreferences mSharedPreferences;
private SharedPreferences.Editor mEditor;
private TextView mEmptyTextView;
private ShoppingListAdapter adapter;
private ActionButton actionButton;
private MaterialDialog addItemdialog = null;
private AdView mAdView;
private IabHelper mHelper;
private String SKU_REMOVE_ADDS = "remove_adds_sku";
private boolean mIsRemoveAdds = false;
private IabHelper.OnIabPurchaseFinishedListener mPurchasedFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    @Override
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
        if (result.isFailure()) {
            Log.d(TAG, "Error purchasing: " + result);
            return;
        }
        else if (purchase.getSku().equals(SKU_REMOVE_ADDS)) {
            // consume the gas and update the UI
            mIsRemoveAdds = true;
            mAdView.setVisibility(View.GONE);
            Toast.makeText(MainActivity.this,"Purchase successful",Toast.LENGTH_LONG).show();
        }
    }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
String publicKey = s1+s2+s3+s4+s5;

    mHelper = new IabHelper(this,publicKey);
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        @Override
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                //error
                Log.d(TAG, "Proglem setting up in-app Billing: " + result);
            }
            //Horay, IAB is fully set up!
            Log.d(TAG, "Horay, IAB is fully set up!");
            queryPurchasedItems();
        }
    });
private void queryPurchasedItems() {
    //check if user has bought "remove adds"
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
        @Override
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            if (result.isFailure()) {
                // handle error here
                Toast.makeText(MainActivity.this,"error",Toast.LENGTH_LONG).show();
            }
            else{
                // does the user have the premium upgrade?
                mIsRemoveAdds = inventory.hasPurchase(SKU_REMOVE_ADDS);
                if(!mIsRemoveAdds) {
                    Toast.makeText(MainActivity.this,"no premium",Toast.LENGTH_LONG).show();
                    mAdView = (AdView) findViewById(R.id.adView);
                    AdRequest adRequest = new AdRequest.Builder().build();
                    mAdView.loadAd(adRequest);
                }else{
                    mAdView.setVisibility(View.GONE);
                    Toast.makeText(MainActivity.this,"premium",Toast.LENGTH_LONG).show();
                }

            }
        }
    };
    mHelper.queryInventoryAsync(mGotInventoryListener);
}
@Override
protected void onStart() {
    super.onStart();
    queryPurchasedItems();
    isListEmpty();
}

@Override
protected void onResume() {
    super.onResume();
    queryPurchasedItems();
    isListEmpty();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mHelper != null) mHelper.dispose();
    mHelper = null;
    mAdView.destroy();
}

Answer

Georgi Koemdzhiev picture Georgi Koemdzhiev · Jun 24, 2015

Finally, I got the whole thing to work and not got this exception "IAB helper is not set up. Can't perform operation: queryInventory" or one more that I was getting "Can't start async operation (consume) because another async operation(consume) is in progress".

The first thing that you have to do is to add 2 methods in the IabHelper.java class:

 public boolean isAsyncInProgress(){
    return mAsyncInProgress;
}
public boolean isSetupDone (){
    return mSetupDone;
}

and than on your main activity:

public class MainActivity extends AppCompatActivity {
private   IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
    @Override
    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
        if (result.isFailure()) {
            // handle error here
            Toast.makeText(MainActivity.this,"error",Toast.LENGTH_LONG).show();
        }
        else{
            // does the user have the premium upgrade?
            mIsRemoveAdds = inventory.hasPurchase(SKU_REMOVE_ADDS);
            if(!mIsRemoveAdds) {
                Toast.makeText(MainActivity.this,"no premium",Toast.LENGTH_LONG).show();
                mAdView = (AdView) findViewById(R.id.adView);
                AdRequest adRequest = new AdRequest.Builder().build();
                mAdView.loadAd(adRequest);
            }else{
                mAdView.setVisibility(View.GONE);
                Toast.makeText(MainActivity.this,"premium",Toast.LENGTH_LONG).show();
            }

        }
    }
};
private IabHelper.OnIabPurchaseFinishedListener mPurchasedFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
    @Override
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
        if (result.isFailure()) {
            Log.d(TAG, "Error purchasing: " + result);
            return;
        }
        else if (purchase.getSku().equals(SKU_REMOVE_ADDS)) {
            // consume the gas and update the UI
            mIsRemoveAdds = true;
            mAdView.setVisibility(View.GONE);
            Toast.makeText(MainActivity.this,"Purchase successful",Toast.LENGTH_LONG).show();
        }
    }
};

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
String publicKey = s1+s2+s3+s4+s5;

    mHelper = new IabHelper(this,publicKey);
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        @Override
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                //error
                Log.d(TAG, "Proglem setting up in-app Billing: " + result);
            }
            if (result.isSuccess()) {
                //Horay, IAB is fully set up!
                Log.d(TAG, "Horay, IAB is fully set up!");
                //queryPurchasedItems;
                mHelper.queryInventoryAsync(mGotInventoryListener);
            }
        }
    });

And now, as it is recommended in Google's guide for the API we have to check what items the user has bought in on start or on resume methods. Here we are going to need the two methods that we added in IabHelper.java class.

   private void queryPurchasedItems() {
    //check if user has bought "remove adds"
    if(mHelper.isSetupDone() && !mHelper.isAsyncInProgress()) {
        mHelper.queryInventoryAsync(mGotInventoryListener);
    }
}

@Override
protected void onStart() {
    super.onStart();
    queryPurchasedItems();
}

@Override
protected void onResume() {
    super.onResume();
    queryPurchasedItems();
    isListEmpty();
}