0

New to Android dev and I have this very annoying, and familiar problem.

Short version: how can I test my app on multiple physical devices w/o buying them? Specifically, I'm trying to test on 4.1 and 4.2 running devices. I can't use an emulator because this involves in-app billing.

Long version:

Today, I got a crash report from a user (android version = 4.2, on device = A1-811 (mango)).

The issue is: IAB helper is not set up. Can't perform operation: queryInventory . I tested the app on 4.3, 5.0, 5.1 and it's fine.

I KNOW that the actual crash happened because I wasn't quitting when I was checking for (!result.isSuccess()) in mhelper.startSetup().

My question is, how do I solve the underlying issue of IabHelper not being set up?! I don't have access to Android 4.2 device...

MY CODE:

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener () {
            public void onIabPurchaseFinished (IabResult result, Purchase purchase) {
                if (mHelper == null)
                    return;

                if (result.isFailure ()) {
                    Log.d (PURCHASE_TAG, "Google's response is a failure.");
                } else {
                    Log.d (PURCHASE_TAG, "Response is successful. purchase.getSKU = " + purchase.getSku ());
                    premium = true;
                }
            }
        };

        IabHelper.QueryInventoryFinishedListener mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener () {
            public void onQueryInventoryFinished (IabResult result, Inventory inventory) {
                Log.d (PURCHASE_TAG, "Processing Google's response.");

                // Check if user has existing purchase.
                if (result.isFailure ()) {
                    Log.d (PURCHASE_TAG, "Google's response is a failure. Response = ");

                } else {
                    Log.d (PURCHASE_TAG, "Google's response is success! getPurchase() = " + inventory.getPurchase (THE_SKU));

                    if (inventory.getPurchase (THE_SKU) == null) {
                        premium = false;
                    } else {
                        premium = inventory.getPurchase (THE_SKU).getSku ().equals (THE_SKU);
                    }
                }

                // Show price if user is not premium, thank you note if the user is premium
                if (premium == true) {
                    Log.d (PURCHASE_TAG, "3 premium = " + premium);
                    priceView.setText ("Thank you for the purchase!");
                } else {
                    if (inventory != null) {
                        String pro_price = inventory.getSkuDetails (THE_SKU).getPrice ();
                        priceView.setText ("" + pro_price);
                    }
                }
            }
        };

        private void startPurchaseQuery () {
            String base64EncodedPublicKey = "the key is generated ...";

            mHelper = new IabHelper (this, base64EncodedPublicKey);

            Log.d (PURCHASE_TAG, "Purchase query started.");

            mHelper.startSetup (new IabHelper.OnIabSetupFinishedListener () {
                public void onIabSetupFinished (IabResult result) {
                    Log.d (PURCHASE_TAG, "IabHelper Setup successful. Querying inventory.");

                    if (!result.isSuccess ()) {
                        Log.d (PURCHASE_TAG, "Error with IabHelper setup.");
return;

                    }

                    if (mHelper == null) return;

                    // IAB is fully set up. Now, let's get an inventory of stuff we own.
                    // Build the SKU list
                    List<String> additionalSkuList;
                    additionalSkuList = new ArrayList<String> ();
                    additionalSkuList.add (THE_SKU);
                    // Make the query
                    mHelper.queryInventoryAsync (true, additionalSkuList, mQueryFinishedListener);

                    Log.d (PURCHASE_TAG, "Query finished. Premium status = " + premium);
                }
            });
        }


    @Override
    protected void onActivityResult (int requestCode, int resultCode, Intent data) {
        Log.d (PURCHASE_TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);

        // Pass on the activity result to the helper for handling
        if (!mHelper.handleActivityResult (requestCode, resultCode, data)) {
            // not handled, so handle it ourselves (here's where you'd
            // perform any handling of activity results not related to in-app
            // billing...
            super.onActivityResult (requestCode, resultCode, data);
        } else {
            Log.d (PURCHASE_TAG, "onActivityResult handled by IABUtil.");
        }
    }



    @Override
    public void onDestroy () {
        super.onDestroy ();
        if (mHelper != null) mHelper.dispose ();
        mHelper = null;
    }
Community
  • 1
  • 1
player87
  • 1,781
  • 1
  • 14
  • 21
  • Don't try doing that. Catch the crash and make sure it's not called without being set up. There is solid chance user has highly specific setup that you wouldn't be able to reproduce anyways. – poss Sep 08 '15 at 22:01
  • If I catch it, is there anyway I can still get an idea of how many of my users will not be able to purchase because of this issue? I'm assuming that I won't get crash reports after what you suggested. – player87 Sep 08 '15 at 22:04
  • Thing is, you are not really losing anything. People who have this issue won't be able to purchase anything anyway. They just won't get annoyed by the crash. – poss Sep 08 '15 at 22:12
  • Sounds good, I'm also going to use Analytics to get an idea of how many users see this issue. If that number is significant, I'll release a PRO version of the app. – player87 Sep 08 '15 at 23:01
  • I think that's a good approach. You'd be basically using crashes as your measurement of how many people have the issue, which is less than ideal. Let me construct this into answer so it's not in 'unanswered' queue. – poss Sep 08 '15 at 23:14

1 Answers1

0

Answer from comments above

It's better to catch the error and patch own code first. Trying to reproduce exact issue why was IAB not set up may not be possible, because of all kinds of modifications user can do on his device (could be bug with specific version of distro user is running, which is almost impossible to find out, or similar). As you suggested, using Analytics to find out how many users have this issue is good approach.

To answer original question, you can create Alpha or Beta versions in Developer Console and invite users with specific versions of Android you'd like to target into testing group. This was you could test issues and crashes directly from Dev. Console even when not directly being owner of the device.

poss
  • 1,759
  • 1
  • 12
  • 27