title: Why android-inapp-billing-v3 library needs two attempts to purchase?
body: <p>I am trying to use android-inapp-billing-v3 library to implement in-app purchases inside my simple app. I'am using this library( <a href="https://github.com/anjlab/android-inapp-billing-v3" rel="nofollow">https://github.com/anjlab/android-inapp-billing-v3</a>)</p>
  
  <p>I have encountered a strange problem: you need to tap on "Purchase" button twice to buy this product. Let me explain what I mean step-by-step.</p>
  
  <p>Our product isn't purchased, we tap on "Purchase" button
  and Google Play window appears
  here we tap on "Buy" and see our transaction completed successfully
  then we tap anywhere to make Google Play window disappeared and instead of entering in onProductPurchased(..) nothnig hapens.
  Ok, we tap on "Purchase" button AGAIN and without any additional Google Play windows onProductPUrchased is accessed.
  I don't know if it's some sort of bug in the library or in my implementation.
  (Sorry for my english)</p>
  
  <p>This is my code:</p>
  
  <pre><code>public class BillingActivity extends Activity implements BillingProcessor.IBillingHandler {
      BillingProcessor bp;
  
  
      public final static String EXTRA_MESSAGE = "kepardvpn.client.MESSAGE";
      private String LOG_TAG = "BillingActivity";
  
  
      int mFlag;
      private String mResult;
      private String mEmail;
      private String mPassword;
      private Functions mFunctions;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Intent intent = getIntent();
          mFlag = intent.getFlags();
          mEmail = intent.getStringExtra(MainActivity.EMAIL);
          mFunctions = Globals.mFunctions;
  
  
          mPassword = intent.getStringExtra(MainActivity.PASSWORD);
  
          bp = new BillingProcessor(this, null, this);
  
          mFunctions.AddLog(2, LOG_TAG, "onCreate");
      }
  
      // IBillingHandler implementation
  
      @Override
      public void onBillingInitialized() {
          /*
           * Called then BillingProcessor was initialized and its ready to purchase
           */
          mFunctions.AddLog(2, LOG_TAG, "onBillignInitilized ");
          try {
              switch (mFlag) {
                  case 0: {
                      mFunctions.AddLog(2, LOG_TAG, "pay_per_month");
                      bp.purchase(this, "pay_per_month");
                  }
                  break;
                  case 1: {
                      mFunctions.AddLog(2, LOG_TAG, "pay_per_month");
                      bp.purchase(this, "pay_per_year");
                  }
                  break;
              }
          } catch (Exception e) {
              mFunctions.AddLog(2, LOG_TAG, "onBillingInitialized exception:" + e.getMessage());
          }
      }
  
      @Override
      public void onProductPurchased(String productId, TransactionDetails details) {
            /*
             * Called then requested PRODUCT ID was successfully purchased
             */
          mFunctions.AddLog(2, LOG_TAG, "Product successfully puchased");
          try {
              if (bp.consumePurchase(productId))  // imediatly after puchase consume product
              {
                  mFunctions.AddLog(2, LOG_TAG, "onProductPurchased " + "product have been consumed");
                  String obj = StringToJsonObject("action", "checkPayment", "email", mEmail, "password", mPassword,
                          "d", "android", "responseData", java.net.URLEncoder.encode(details.purchaseInfo.responseData, "utf-8"),
                          "signature", java.net.URLEncoder.encode(details.purchaseInfo.signature, "utf-8"), "response", "text");
  
                  mFunctions.setPaymentResponseData(details.purchaseInfo.responseData);
                  mFunctions.setPaymentSignature(details.purchaseInfo.signature);
                  mFunctions.ActivatePayAccountTask(obj);
                  //mFunctions.updatePreferences();
  
              } else // product could not have been consumed
              {
                  mFunctions.AddLog(2, LOG_TAG, "onProductPurchased " + "product could not have been consumed");
              }
          } catch (Exception e) {
              mFunctions.AddLog(2, LOG_TAG, "onProductPurchased exception:" + e.getMessage());
  
          }
          ;
  
      }
  
      @Override
      public void onBillingError(int errorCode, Throwable error) {
  
          switch (errorCode) {
              case Constants.BILLING_RESPONSE_RESULT_DEVELOPER_ERROR:
  
                  mFunctions.AddLog(2, LOG_TAG, "onBillingError," + "Invalid arguments provided to the API." + "Error code:" + errorCode);
                  break;
              case Constants.BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE:
                  sendMessage(getString(R.string.billing_not_supported_message));
                  break;
              case Constants.BILLING_RESPONSE_RESULT_USER_CANCELED:
                  mFunctions.AddLog(2, LOG_TAG, "onBillingError," + "User canceled purchase");
                  break;
          }
          mFunctions.AddLog(2, LOG_TAG, "Error code:" + errorCode);
      }
  
  
      @Override
      public void onDestroy() {
          if (bp != null)
              bp.release();
          mFunctions.AddLog(2, LOG_TAG, "onDestroy");
          super.onDestroy();
      }
  
      @Override
      public void onPurchaseHistoryRestored() {
          /*
           * Called then purchase history was restored and the list of all owned PRODUCT ID's
           * was loaded from Google Play
           */
          mFunctions.AddLog(2, LOG_TAG, "onPurchasedHistoryRestored");
      }
  
      void sendMessage(String message) {        
          mFunctions.ShowError(message);
      }
  
      public String StringToJsonObject(String... val) {
          JSONObject obj = new JSONObject();
          try {
              for (int i = 0; i &lt; val.length - 1; i += 2) {
                  obj.put(val[i], val[i + 1]);
              }
          } catch (Exception e) {
          }
          return obj.toString();
      }
  
  }
  </code></pre>