1

I created a subscription product and when people try to buy it, they click from my app to the app store, and they get an error "item not found"

But the items shows up as live in my developer console.

Here is how I call it:

Here is the onActivityResult() from this method:

protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    sendEmail(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data

results in this:

onActivityResult(10001,0,Intent { (has extras) }

and the onIabPurchaseFinished

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() 
{
    public void onIabPurchaseFinished(IabResult result, Purchase purchase) 
    {
        sendEmail(TAG, "Purchase finished: " + result + ", purchase: " + purchase);

never seems to get executed.

And

public void onUpgradeAppButtonClicked( ) 
{
    sendEmail(TAG, "Buy button clicked; launching purchase flow for upgrade. SKU: " + SKU_SUBSCRIPTION + " and RC_REQUEST: " + RC_REQUEST );
    //setWaitScreen(true);
    mHelper.launchPurchaseFlow(this, SKU_SUBSCRIPTION, RC_REQUEST, mPurchaseFinishedListener);
}

resulted in this:

Buy button clicked; launching purchase flow for upgrade. SKU: my_sku and RC_REQUEST: 10001

Would anyone know why the error occured? Could it be that this happens in some older phones?

Also, if someone could try it on their phone maybe, that would help because I only have one phone to test with :) This is the link to the app: https://play.google.com/store/apps/details?id=com.problemio&hl=en

and to get to the billing is on the home screen the very bottom button.

EDIT:

I know that sometimes it takes time for the in-app product to truly go live in the Android system, but it says live in my dev console :)

EDIT:

In my IABHelper.java I have this:

/**
 * Same as calling {@link #launchPurchaseFlow(Activity, String, int, OnIabPurchaseFinishedListener, String)}
 * with null as extraData.
 */
public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
    launchPurchaseFlow(act, sku, requestCode, listener, "");
}

and then this:

/**
 * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app purchase,
 * which will involve bringing up the Google Play screen. The calling activity will be paused while
 * the user interacts with Google Play, and the result will be delivered via the activity's
 * {@link android.app.Activity#onActivityResult} method, at which point you must call
 * this object's {@link #handleActivityResult} method to continue the purchase flow. This method
 * MUST be called from the UI thread of the Activity.
 *
 * @param act The calling activity.
 * @param sku The sku of the item to purchase.
 * @param requestCode A request code (to differentiate from other responses --
 *     as in {@link android.app.Activity#startActivityForResult}).
 * @param listener The listener to notify when the purchase process finishes
 * @param extraData Extra data (developer payload), which will be returned with the purchase data
 *     when the purchase completes. This extra data will be permanently bound to that purchase
 *     and will always be returned when the purchase is queried.
 */
public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener, String extraData) {
    checkSetupDone("launchPurchaseFlow");
    flagStartAsync("launchPurchaseFlow");
    IabResult result;

    try {
        logDebug("Constructing buy intent for " + sku);
        Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, ITEM_TYPE_INAPP, extraData);
        int response = getResponseCodeFromBundle(buyIntentBundle);
        if (response != BILLING_RESPONSE_RESULT_OK) {
            logError("Unable to buy item, Error response: " + getResponseDesc(response));

            result = new IabResult(response, "Unable to buy item");
            if (listener != null) listener.onIabPurchaseFinished(result, null);
        }

        PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
        logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode);
        mRequestCode = requestCode;
        mPurchaseListener = listener;
        act.startIntentSenderForResult(pendingIntent.getIntentSender(),
                                       requestCode, new Intent(),
                                       Integer.valueOf(0), Integer.valueOf(0),
                                       Integer.valueOf(0));
    }
    catch (SendIntentException e) {
        logError("SendIntentException while launching purchase flow for sku " + sku);
        e.printStackTrace();

        result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
        if (listener != null) listener.onIabPurchaseFinished(result, null);
    }
    catch (RemoteException e) {
        logError("RemoteException while launching purchase flow for sku " + sku);
        e.printStackTrace();

        result = new IabResult(IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow");
        if (listener != null) listener.onIabPurchaseFinished(result, null);
    }
}
Genadinik
  • 18,153
  • 63
  • 185
  • 284
  • I like your app after I download it on the play store. all is working well but got item not found exception while donate subscription to the app. please check my answer below. – Maulik Apr 23 '13 at 05:54

1 Answers1

1

I have not tried the subscription in app billing but according to my knowledge check my answer below. Make sure two thing your product key that you given for the product is correct. and use IabHelper.ITEM_TYPE_SUBS in the item type.

  1) static final String SKU_SUBSCRIPTION = "your product id should be here";

  2) mHelper.launchPurchaseFlow(youractivity.this,
                            SKU_SUBSCRIPTION, IabHelper.ITEM_TYPE_SUBS, 
                            RC_REQUEST, mPurchaseFinishedListener, payload); 

please let me infirm it is working for you. Hope it will help you.

check IabHelper method:

     // The listener registered on launchPurchaseFlow, which we have to call back when
   // the purchase finishes
   OnIabPurchaseFinishedListener mPurchaseListener;

   public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
       launchPurchaseFlow(act, sku, requestCode, listener, "");
   }

   public void launchPurchaseFlow(Activity act, String sku, int requestCode, 
           OnIabPurchaseFinishedListener listener, String extraData) {
       launchPurchaseFlow(act, sku, ITEM_TYPE_INAPP, requestCode, listener, extraData); 
   }

   public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, 
           OnIabPurchaseFinishedListener listener) {
       launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, "");
   }

   public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, 
           OnIabPurchaseFinishedListener listener, String extraData) {
       launchPurchaseFlow(act, sku, ITEM_TYPE_SUBS, requestCode, listener, extraData); 
   }

   /**
    * Initiate the UI flow for an in-app purchase. Call this method to initiate an in-app purchase,
    * which will involve bringing up the Google Play screen. The calling activity will be paused while
    * the user interacts with Google Play, and the result will be delivered via the activity's
    * {@link android.app.Activity#onActivityResult} method, at which point you must call
    * this object's {@link #handleActivityResult} method to continue the purchase flow. This method
    * MUST be called from the UI thread of the Activity.
    *
    * @param act The calling activity.
    * @param sku The sku of the item to purchase.
    * @param itemType indicates if it's a product or a subscription (ITEM_TYPE_INAPP or ITEM_TYPE_SUBS)
    * @param requestCode A request code (to differentiate from other responses --
    *     as in {@link android.app.Activity#startActivityForResult}).
    * @param listener The listener to notify when the purchase process finishes
    * @param extraData Extra data (developer payload), which will be returned with the purchase data
    *     when the purchase completes. This extra data will be permanently bound to that purchase
    *     and will always be returned when the purchase is queried.
    */
   public void launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode,
                       OnIabPurchaseFinishedListener listener, String extraData) {
       checkSetupDone("launchPurchaseFlow");
       flagStartAsync("launchPurchaseFlow");
       IabResult result;

       if (itemType.equals(ITEM_TYPE_SUBS) && !mSubscriptionsSupported) {
           IabResult r = new IabResult(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE, 
                   "Subscriptions are not available.");
           if (listener != null) listener.onIabPurchaseFinished(r, null);
           return;
       }

       try {
           logDebug("Constructing buy intent for " + sku + ", item type: " + itemType);
           Bundle buyIntentBundle = mService.getBuyIntent(3, mContext.getPackageName(), sku, itemType, extraData);
           int response = getResponseCodeFromBundle(buyIntentBundle);
           if (response != BILLING_RESPONSE_RESULT_OK) {
               logError("Unable to buy item, Error response: " + getResponseDesc(response));

               result = new IabResult(response, "Unable to buy item");
               if (listener != null) listener.onIabPurchaseFinished(result, null);
               return;
           }

           PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
           logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode);
           mRequestCode = requestCode;
           mPurchaseListener = listener;
           mPurchasingItemType = itemType;
           act.startIntentSenderForResult(pendingIntent.getIntentSender(),
                                          requestCode, new Intent(),
                                          Integer.valueOf(0), Integer.valueOf(0),
                                          Integer.valueOf(0));
       }
       catch (SendIntentException e) {
           logError("SendIntentException while launching purchase flow for sku " + sku);
           e.printStackTrace();

           result = new IabResult(IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
           if (listener != null) listener.onIabPurchaseFinished(result, null);
       }
       catch (RemoteException e) {
           logError("RemoteException while launching purchase flow for sku " + sku);
           e.printStackTrace();

           result = new IabResult(IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow");
           if (listener != null) listener.onIabPurchaseFinished(result, null);
       }
   }
Maulik
  • 3,316
  • 20
  • 31
  • Thank you. What I am using is this call: mHelper.launchPurchaseFlow(this, SKU_SUBSCRIPTION, RC_REQUEST, mPurchaseFinishedListener); which does not have the ITEM_TYPE_SUBS or the payload parameter. Are you using an older api version? I am not sure payload is required – Genadinik Apr 23 '13 at 12:32
  • intersting...how do you construct the payload object? I don't seem to find that in their example that I have. – Genadinik Apr 23 '13 at 12:47
  • @Genadinik am using version 3 of in App purchase. you can also chek in default demo in the android sdk. may be it will available after feb 2013 check this link http://android-developers.blogspot.in/2012/12/in-app-billing-version-3.html. – Maulik Apr 23 '13 at 12:51
  • don't know much about the payload but I have just use an empty string String payload = ""; – Maulik Apr 23 '13 at 12:56
  • interesting. I get this error: The method launchPurchaseFlow(Activity, String, int, IabHelper.OnIabPurchaseFinishedListener, String) in the type IabHelper is not applicable for the arguments (SupportActivity, String, String, int, IabHelper.OnIabPurchaseFinishedListener, String) for this method: mHelper.launchPurchaseFlow(this, SKU_SUBSCRIPTION, IabHelper.ITEM_TYPE_INAPP, RC_REQUEST, mPurchaseFinishedListener, ""); – Genadinik Apr 23 '13 at 13:12
  • I think something might be different in the examples we are working with. I just got the latest example yesterday from the sdk manager. – Genadinik Apr 23 '13 at 13:13
  • I am also surprising I have both of this methods as you told me and which I have written in my answer. Can you please tell me are you have "launchSubscriptionPurchaseFlow" method for the subscription in IabHelper class? – Maulik Apr 23 '13 at 13:34
  • I added the IABHelper method to my original question – Genadinik Apr 23 '13 at 13:56
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/28749/discussion-between-maulik-and-genadinik) – Maulik Apr 23 '13 at 14:09