Android – Google’s IAB API3 getSkuDetails() method returns failed 5: Developer Error

androideclipsein-app-billingin-app-purchase

I am trying to incorporate Google's in-app-billing API3 in my code that has been using API2.

My call to mHelper (the IabHelper object) succeeds, so I am connecting to Google's servers. It appears that I can determine owned items, as my QueryInventoryFinishedListener returns a valid Inventory with all my purchased items. I am also able to execute a purchase.

However, querying for sku details fails (getSkuDetails()). Here is all IabHelper-related LogCat output from Eclipse (I removed my package name and product SKUs) leading up to the failure:

12-31 11:47:04.642: D/IabHelper(13633): Starting in-app billing setup.
12-31 11:47:04.832: D/IabHelper(13633): Billing service connected.
12-31 11:47:04.832: D/IabHelper(13633): Checking for in-app billing 3 support.
12-31 11:47:04.832: D/IabHelper(13633): In-app billing version 3 supported for com.XXXX.XXXX
12-31 11:47:04.832: D/IabHelper(13633): Subscriptions AVAILABLE.
12-31 11:47:04.842: D/IabHelper(13633): Starting async operation: refresh inventory
12-31 11:47:04.842: D/IabHelper(13633): Querying owned items, item type: inapp
12-31 11:47:04.842: D/IabHelper(13633): Package name: com.XXXX.XXXX
12-31 11:47:04.842: D/IabHelper(13633): Calling getPurchases with continuation token: null
12-31 11:47:04.912: D/IabHelper(13633): Owned items response: 0
12-31 11:47:04.912: D/IabHelper(13633): Sku is owned: com.XXXX.XXXX.item_one
12-31 11:47:04.922: D/IabHelper(13633): Sku is owned: com.XXXX.XXXX.item_two
...
(and 45 other items)
...
12-31 11:47:05.012: D/IabHelper(13633): Continuation token: null
12-31 11:47:05.012: D/IabHelper(13633): Querying SKU details.
12-31 11:47:05.012: D/IabHelper(13633): getSkuDetails() failed: 5:Developer Error
12-31 11:47:05.012: D/IabHelper(13633): Ending async operation: refresh inventory

It doesn't seem like a signing issue, since I can successfully connect and make a purchase.

Has anybody else been having issues where getSkuDetails() fails with the "Developer Error" message, while other aspects of in-app-billing work?

Thanks for your time!

Best Answer

I've experienced the same problem. The issue appears to occur when you've more than 20 SKUs in your inventory.

The solution was to get the SKU details in chunks. Replace querySkuDetails in IabHelper.java with:

int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus)
    throws RemoteException, JSONException {
    logDebug("Querying SKU details.");
    ArrayList<String> skuList = new ArrayList<String>();
    skuList.addAll(inv.getAllOwnedSkus(itemType));
    if (moreSkus != null) {
        for (String sku : moreSkus) {
            if (!skuList.contains(sku)) {
                skuList.add(sku);
            }
        }
    }

    if (skuList.size() == 0) {
        logDebug("queryPrices: nothing to do because there are no SKUs.");
        return BILLING_RESPONSE_RESULT_OK;
    }

    while (skuList.size() > 0) {
        ArrayList<String> skuSubList = new ArrayList<String>(
                skuList.subList(0, Math.min(19, skuList.size())));
        skuList.removeAll(skuSubList);

        Bundle querySkus = new Bundle();
        querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skuSubList);
        Bundle skuDetails = mService.getSkuDetails(3,
                mContext.getPackageName(), itemType, querySkus);

        if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
            int response = getResponseCodeFromBundle(skuDetails);
            if (response != BILLING_RESPONSE_RESULT_OK) {
                logDebug("getSkuDetails() failed: "
                        + getResponseDesc(response));
                return response;
            } else {
                logError("getSkuDetails() returned a bundle with neither an error nor a detail list.");
                return IABHELPER_BAD_RESPONSE;
            }
        }

        ArrayList<String> responseList = skuDetails
                .getStringArrayList(RESPONSE_GET_SKU_DETAILS_LIST);

        for (String thisResponse : responseList) {
            SkuDetails d = new SkuDetails(itemType, thisResponse);
            logDebug("Got sku details: " + d);
            inv.addSkuDetails(d);
        }
    }
    return BILLING_RESPONSE_RESULT_OK;
}

This method gets the SKUs in chunks of 18. It worked for me.

Related Topic