I have a situation where I tested on a test device with the item id: android.test.purchased
And things worked. Then once I changed that string with the real item id, I started getting Item Not Found error when I pressed the buy button.
Also the buy item is a subscription and not a 1-time purchase. Does that make a difference?
I was not sure which part of the code may be at fault, or what may be missing so here is the class for this:
public class SubscribeIntroActivity extends BaseActivity
{
IabHelper mHelper;
// Does the user have the premium upgrade?
boolean isSubscriber = false;
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 105;
// Subscribe SKU
static final String SUBSCRIBE_SKU = "11";
// Subscribe SKU
static final String TAG = "BILLING";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.subscribe_intro);
String base64EncodedPublicKey = "my_real_key";
// Create the helper, passing it our context and the public key to verify signatures with
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result)
{
if (!result.isSuccess())
{
// Oh noes, there was a problem.
//complain("Problem setting up in-app billing: " + result);
return;
}
// Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own.
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
// Listener that's called when we finish querying the items we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
if (result.isFailure())
{
//complain("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
// Do we have the premium upgrade?
isSubscriber = inventory.hasPurchase(SUBSCRIBE_SKU);
Log.d(TAG, "User is " + (isSubscriber ? "SUBSCRIBER" : "NOT SUBSCRIBER"));
// Check for gas delivery -- if we own gas, we should fill up the tank immediately
if (inventory.hasPurchase( SUBSCRIBE_SKU ))
{
Log.d(TAG, "HAS SUBSCRIPTION");
return;
}
//updateUi();
// TODO: TELL USER HE IS SUBSCIBED AND TAKE THEM TO THE QUESTION
//setWaitScreen(false);
Log.d(TAG, "Initial inventory query finished; enabling main UI.");
}
};
Button subscribe = (Button)findViewById(R.id.subscribe);
subscribe.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View v)
{
// FIRST CHECK IF THE USER IS ALREADY A SUBSCRIBER.
mHelper.launchPurchaseFlow(SubscribeIntroActivity.this, SUBSCRIBE_SKU, RC_REQUEST, mPurchaseFinishedListener);
// Send me an email that a comment was submitted on a question.
//sendEmail("My Questions -> Add Question", "Someone clicked on add-question from my questions. User id: " + user_id );
//Intent myIntent = new Intent(MotivationActivity.this, WePromoteActivity.class);
//MotivationActivity.this.startActivity(myIntent);
}
});
// mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
// public void onIabSetupFinished(IabResult result)
// {
// if (!result.isSuccess())
// {
// // Oh noes, there was a problem.
//
// Log.d("INAPP BILLING", "Problem setting up In-app Billing: " + result);
// }
//
// // Hooray, IAB is fully set up!
//
//
// // First arg is whether product details should be retrieved
// // The List argument consists of one or more product IDs (also called SKUs) for the products that you want to query.
// // the QueryInventoryFinishedListener argument specifies a listener is
// // notified when the query operation has completed
// // and handles the query response.
//// mHelper.queryInventoryAsync(false, new ArrayList ( ).add("1"),
//// mQueryFinishedListener);
//
// //mHelper.queryInventoryAsync(mGotInventoryListener);
//
//
//// mHelper.launchPurchaseFlow(SubscribeIntroActivity.this, "11" , 105, mPurchaseFinishedListener, "" );
// }
// });
}
IabHelper.QueryInventoryFinishedListener
mQueryFinishedListener = new IabHelper.QueryInventoryFinishedListener()
{
public void onQueryInventoryFinished(IabResult result, Inventory inventory)
{
if (result.isFailure()) {
// handle error
return;
}
String applePrice =
inventory.getSkuDetails("1").getPrice();
String bananaPrice =
inventory.getSkuDetails(SUBSCRIBE_SKU).getPrice();
}
// update the UI
};
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
= new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase)
{
if (result.isFailure())
{
Log.d("ERROR", "Error purchasing: " + result);
return;
}
else if (purchase.getSku().equals("1"))
{
// consume the gas and update the UI
}
else if (purchase.getSku().equals(SUBSCRIBE_SKU))
{
// give user access to premium content and update the UI
Log.d(TAG, "PURCHASED: " + result);
}
}
};
IabHelper.QueryInventoryFinishedListener mGotInventoryListener
= new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result,
Inventory inventory) {
if (result.isFailure()) {
// handle error here
}
else
{
// does the user have the premium upgrade?
isSubscriber = inventory.hasPurchase(SUBSCRIBE_SKU);
// update UI accordingly
}
}
};
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(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(TAG, "onActivityResult handled by IABUtil.");
}
}
@Override
public void onDestroy()
{
super.onDestroy();
if (mHelper != null) mHelper.dispose();
mHelper = null;
}
}
I don’t think the new in-app billing version 3 currently supports subscriptions. I could be wrong, but I haven’t seen any mention of subscriptions in the sample code or documentation, so that could be why you’re receiving the the “Item not found” error.
In general, to test purchasing a real item, you need to upload a version of your app to the developer console (but you don’t need to publish it), and you have to be using the same (signed) version to test with. It also takes Google Play some time to process/propagate newly added items…so sometimes you unfortunately just need to wait. Check out developer.android.com/training/in-app-billing/test-iab-app.html if you haven’t already.