简体   繁体   中英

In-app billing query inventory in AsyncTask?

I followed this tutorial to add a loading screen to the launch of my app while data is loaded with AsyncTask's doInBackground() function.

My app also features an in-app billing premium upgrade and I would like to query the inventory to check for this on launch. However the IabHelper functions are already asynchronous.

How can I integrate the IabHelper checks into doInBackground() so that the main activity is only loaded when everything has successfully completed?

My billing code is as follows:

private void checkForPremiumPurchase()
{
    billingHelper = new IabHelper(this, Constants.BASE_64_KEY);
    //Start setup. This is asynchronous and the specified listener will be called once setup completes.
    billingHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            if(result.isSuccess()) {
                billingHelper.queryInventoryAsync(mGotInventoryListener);
            }
        }
    });
}

//Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener()
{
    @Override
    public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
        if(result.isSuccess()) {
            isPremium = inventory.hasPurchase(Constants.SKU_PREMIUM);
            Log.d(Constants.TAG, "App is " + (isPremium ? "PREMIUM" : "NOT PREMIUM"));
        }
    }
};

AsyncTask is really useful, and helps you put long-running jobs onto a background thread, and give you a nice clean mechanism for updating the UI before, during, and after that background task runs ... all without messing with threads directly.

Some other Android APIs, however, are setup to let you initiate calls on the main (UI) thread, and then behind-the-scenes, they will do their work on a background thread (they could even be using AsyncTask , although you don't necessarily care).

In this case, the IabHelper methods you're using are asynchronous , and they will allow you to initiate them from the main thread, without blocking the UI.

Therefore, there is no need to run them in the same AsyncTask#doInBackground() method that you're using for other work, just to get the work off the main thread.


I see two options:

1) Concurrent Loading / IAB Request

Ideally, if you need to load some data at startup (and are using AsyncTask for this), you could also kick off your In-App Billing request at the same time.

You describe a main activity , so I'm assuming your app starts with a splash activity of some kind (?). In that splash activity, you could use:

public void onCreate(Bundle savedInstanceState) {
    new MyLoadingAsyncTask().execute();

    checkForPremiumPurchase();
}

and then you would launch the main activity when the IAB check completes:

public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
    isPremium = false;
    if(result.isSuccess()) {
        isPremium = inventory.hasPurchase(Constants.SKU_PREMIUM);
        Log.d(Constants.TAG, "App is " + (isPremium ? "PREMIUM" : "NOT PREMIUM"));
    }
    Intent i = new Intent(self, MainActivity.class);
    i.putExtra("IsPremium", isPremium);
    startActivity(i);
}

This assumes that the network IAB transaction will take longer than your app's normal "loading" process. (post a comment if that assumption isn't valid, and I'll handle that case)

2) Serialized Loading, then IAB

If there's something else about your app's design that requires you to "finish loading" and then initiate the IAB request, then you can call checkForPremiumPurchase() when your AsyncTask finishes its work:

 protected void onPostExecute(Long result) {
     checkForPremiumPurchase();
 }

AsyncTask#onPostExecute() gets called on the main thread when the loading completes, and checkForPremiumPurchase() is safe to call on the main thread.

Comment

In general, I'd recommend against delaying the startup of your app to check for a premium upgrade. Ideally, you'd find a clever way to save this state (premium purchased) once , and then avoid future checks. Your users will appreciate that.

However, I don't know what the difference between free / premium is for your app, and whether that difference shows up immediately ... so, maybe this is something you can't avoid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM