Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android In-app billing error: Illegal state for operation (launchPurchaseFlow): IAB helper is not set up

I tried setting up InApp purchases for a donation with the guide provided by Google but when I call the activity (which should return if it was a success or not) but it throws this error:

In-app billing error: Illegal state for operation (launchPurchaseFlow): IAB helper is not set up

The activity is called with this method:

public boolean donation() {
        int success = 0;
        Intent intent = new Intent(Main.this, Donate.class);
        startActivityForResult(intent, success);
        if (success != 0) {
            return true;
        }
        else return false;
    }

And the Donate class (which I tried coding with the guide) looks like this:

import java.math.BigInteger;
import java.security.SecureRandom;
import maturaarbeit.nicola_pfister.marks.R;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;

public class Donate extends Activity {

    IabHelper mHelper;

    private static final String TAG = "Donate";
    private String payload;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        String base64EncodedPublicKey = getKey();
        mHelper = new IabHelper(this, base64EncodedPublicKey);

        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {

            @Override
            public void onIabSetupFinished(IabResult result) {
                if (!result.isSuccess()) {
                    Log.d(TAG, "Problem setting up In-app Billing: " + result); 
                }
            }
        });

        SharedPreferences prefs = getSharedPreferences(getPackageName() + "_preferences", MODE_PRIVATE);    //Add shared preferences
        payload = prefs.getString("devpayload", null);
        if (payload == null) {
            payload = getPayload();

            Editor editor = prefs.edit();
            editor.putString("devpayload", payload)
            .apply();
        }
        mHelper.launchPurchaseFlow(this, "donation_1chf", 1, mPurchaseFinishedListener, payload);
        finish();
    }

    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {

        @Override
        public void onIabPurchaseFinished(IabResult result, Purchase info) {
            if (result.isFailure()) {
                Log.d(TAG, "Error purchasing: " +result);
                return;
            }
            else if (info.getDeveloperPayload().equals(payload)) {
                return;
            }
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
        if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
            super.onActivityResult(requestCode, resultCode, data);
        } else {
            Log.i(TAG, "onActivityResult handled by IABUtil.");
        }
    }

    private String getKey() {
        //Code for building public key
    }

    private String getPayload() {
      SecureRandom random = new SecureRandom();
      {
        return new BigInteger(130, random).toString(32);
      }
    }

    @Override
    protected void onDestroy() {
        if (mHelper != null) mHelper.dispose();
        mHelper = null;
        super.onDestroy();
    }

}

It is supposed to generate a dev payload which is stored in shared prefs if there isn't already one. If you need any additional information feel free to ask.

Thanks for your help!

like image 394
NiPfi Avatar asked May 05 '13 18:05

NiPfi


2 Answers

You have to wait for onIabSetupFinishedListener to return before calling launchPurchaseFlow - move those lines into your onIabSetupFinishedListener's onIabSetupFinished method to ensure that the IabHelper's setup is complete:

mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        @Override
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                Log.d(TAG, "Problem setting up In-app Billing: " + result); 
            }
            else { // Only launch the purchase flow if setup succeeded
                mHelper.launchPurchaseFlow(Donate.this, "donation_1chf", 1,
                    mPurchaseFinishedListener, payload);
            }
        }
    });
like image 103
ianhanniballake Avatar answered Nov 19 '22 08:11

ianhanniballake


You should use real device for app billing because when using emulator some parameters are being null and it causes runtime errors.

like image 4
Burak iren Avatar answered Nov 19 '22 10:11

Burak iren