/**
  * Requests to confirm all pending notifications for the specified item.
  *
  * @param context
  * @param itemId id of the item whose purchase must be confirmed.
  * @return true if pending notifications for this item were found, false otherwise.
  */
 public static boolean confirmNotifications(Context context, String itemId) {
   final Set<String> notifications = manualConfirmations.get(itemId);
   if (notifications != null) {
     confirmNotifications(context, notifications.toArray(new String[] {}));
     return true;
   } else {
     return false;
   }
 }
  /**
   * Called after the response to a {@link net.robotmedia.billing.request.GetPurchaseInformation}
   * request is received. Registers all transactions in local memory and confirms those who can be
   * confirmed automatically.
   *
   * @param context
   * @param signedData signed JSON data received from the Market Billing service.
   * @param signature data signature.
   */
  protected static void onPurchaseStateChanged(
      Context context, String signedData, String signature) {
    debug("Purchase state changed");

    if (TextUtils.isEmpty(signedData)) {
      Log.w(LOG_TAG, "Signed data is empty");
      return;
    } else {
      debug(signedData);
    }

    if (!debug) {
      if (TextUtils.isEmpty(signature)) {
        Log.w(LOG_TAG, "Empty signature requires debug mode");
        return;
      }
      final ISignatureValidator validator =
          BillingController.validator != null
              ? BillingController.validator
              : new DefaultSignatureValidator(BillingController.configuration);
      if (!validator.validate(signedData, signature)) {
        Log.w(LOG_TAG, "Signature does not match data.");
        return;
      }
    }

    List<Transaction> purchases;
    try {
      JSONObject jObject = new JSONObject(signedData);
      if (!verifyNonce(jObject)) {
        Log.w(LOG_TAG, "Invalid nonce");
        return;
      }
      purchases = parsePurchases(jObject);
    } catch (JSONException e) {
      Log.e(LOG_TAG, "JSON exception: ", e);
      return;
    }

    ArrayList<String> confirmations = new ArrayList<String>();
    for (Transaction p : purchases) {
      if (p.notificationId != null && automaticConfirmations.contains(p.productId)) {
        confirmations.add(p.notificationId);
      } else {
        // TODO: Discriminate between purchases, cancellations and
        // refunds.
        addManualConfirmation(p.productId, p.notificationId);
      }
      storeTransaction(context, p);
      notifyPurchaseStateChange(p.productId, p.purchaseState);
    }
    if (!confirmations.isEmpty()) {
      final String[] notifyIds = confirmations.toArray(new String[confirmations.size()]);
      confirmNotifications(context, notifyIds);
    }
  }