Question

I am implementing the In-App Billing service in my app. I set up in onCreate() the call to the IabHelper.queryInventoryAsync() to retrieve previous purchases. If the item is purchased, I set a global boolean variable to true. Meanwhile, in onCreateOptionsMenu(), I check that variable whether to remove a MenuItem or not. My problem is that onCreateOptionsMenu(), as expected, is sometimes called before the async task is done setting my boolean variable. I need a solution to tell onCreateOptionsMenu() to wait for that task to set the boolean value, so that it can create the menu accordingly. Here's the code in detail:

@Override
protected void onCreate(Bundle savedInstanceState) {  

//other  stuff...

   helper.queryInventoryAsync(new IabHelper.QueryInventoryFinishedListener() {
                public void onQueryInventoryFinished(IabResult result,
                                                     Inventory inventory) {

                    if (result.isFailure()) {
                        // handle error here   
                        return;                        
                    }

                    if (inventory.hasPurchase(REMOVE_ADS_SKU)) {  
                        //item purchased. set control variable
                        isNoAds = true;
                    } 

                }
            });
}

@Override
public boolean onCreateOptionsMenu(final Menu menu) {

    getMenuInflater().inflate(R.menu.main, menu);

    //if the control variable is true, remove the option to buy ad-free version
    if (isNoAds) menu.removeItem(R.id.action_remove_ads);

    return super.onCreateOptionsMenu(menu);
}
Was it helpful?

Solution

I've found that the most robust way to do this is by invalidating the whole menu. So, when you get your async result (in onQueryInventoryFinished) just call:

invalidateOptionsMenu();

or, if you are using a FragmentActivity (SherlockFragmentActivity or ActionBarActivity)

supportInvalidateOptionsMenu();

In this way the menu will be recreated and you can safely add or remove items as you need.

OTHER TIPS

Maybe using onPrepareOptionMenu might do the trick. The docs (http://developer.android.com/reference/android/app/Activity.html#onPrepareOptionsMenu%28android.view.Menu%29) states that it's used to prepare what should be displayed. You keep the xml inflate in the onCreateOptionsMenu and then do the following:

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    menu.findItem(R.id.action_remove_ads).setVisible(!isNoAds);
    return super.onPrepareOptionsMenu(menu);
}

You still initialize the isNoAds variable to true in the onCreate method to be sure it's not displayed immediatly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top