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();
}
Your OnIabSetupFinishedListener checks for (!result.isSuccess())
but you don't return or abort here in case the resulst is NOT successful.
I think your mHelper.startSetup fails ,and you are not handling this failure.
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:
and than on your main activity:
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.