This is my first time working with In App Billing in android. My goal is to create purchasable item somewhat like pro version unlock for the app.
My problem is that it keeps giving me these errors.
Please take note that the license key is correct, my google account is already added as a tester in the console, the product sku already exists and alpha build of the apk is already uploaded to the console.
Here's my code,
public class ProVersionActivity extends AppCompatActivity {
public static final String TAG = "ProVersionActivity";
public static final String SKU_PRO_VERSION = "vollversion";
private boolean mProVersionPurchased = false;
private String mPayload = "";
//(arbitrary) request code for the purchase flow
public static final int RC_REQUEST = 10001;
private Button mInAppPurchaseButton = null;
private WebView mWebView = null;
private IabHelper mHelper = null;
private ProgressDialog mProgressDialog = null;
private static final String LICENSE_KEY = "LICENSE_KEY";
//Listener that's called when we finish querying the items and subscriptions we own
private IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
Log.d(TAG, "Query inventory finished.");
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null) return;
// Is it a failure?
if (result.isFailure()) {
complain("Failed to query inventory: " + result);
return;
}
Log.d(TAG, "Query inventory was successful.");
/*
* Check for items we own. Notice that for each purchase, we check
* the developer payload to see if it's correct! See
* verifyDeveloperPayload().
*/
// Do we have the infinite gas plan
Purchase proVersionPurchase = inventory.getPurchase(SKU_PRO_VERSION);
mProVersionPurchased = (proVersionPurchase != null && verifyDeveloperPayload(proVersionPurchase));
Log.d(TAG, "User " + (mProVersionPurchased ? "HAS" : "DOES NOT HAVE") + " proversion");
if(mProVersionPurchased){
//this means user already purchased the full version
setProversionPurchased(mProVersionPurchased);
}
Log.d(TAG, "Initial inventory query finished");
}
};
// Callback for when a purchase is finished
private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
Log.d(TAG, "Error purchasing: " + result);
complain("Error purchasing: " + result);
//setWaitScreen(false);
dismissProgressDialog();
return;
}
if (!verifyDeveloperPayload(purchase)) {
Log.d(TAG, "Error purchasing. Authenticity verification failed.");
complain("Error purchasing. Authenticity verification failed.");
//setWaitScreen(false);
dismissProgressDialog();
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_PRO_VERSION)) {
// bought the infinite gas subscription
Log.d(TAG, "Proversion purchased.");
alert("Thank you for purchasing the Proversion!");
mProVersionPurchased = true;
setProversionPurchased(mProVersionPurchased);
//setWaitScreen(false);
dismissProgressDialog();
ProVersionActivity.this.finish();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pro_version);
getSupportActionBar().setTitle(R.string.vollversion);
//for the progress dialog
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setCancelable(false);
mProgressDialog.setCanceledOnTouchOutside(false);
mProgressDialog.setMessage("Processing...");
mProgressDialog.setIndeterminate(true);
String lang = getString(R.string.lang);
mWebView = (WebView) findViewById(R.id.webView);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("file:///android_asset/html/" + lang + "_iap.htm");
/**
* preparing in app billing
* */
String base64EncodedPublicKey = LICENSE_KEY;
// compute your public key and store it in base64EncodedPublicKey
mHelper = new IabHelper(this, base64EncodedPublicKey);
// enable debug logging (for a production application, you should set this to false).
mHelper.enableDebugLogging(true);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Have we been disposed of in the meantime? If so, quit.
if (mHelper == null)
return;
// IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
mInAppPurchaseButton = (Button) findViewById(R.id.in_app_purchase_button);
mInAppPurchaseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!mHelper.subscriptionsSupported()) {
Log.d(TAG, "Subscriptions not supported on your device yet. Sorry!");
complain("Subscriptions not supported on your device yet. Sorry!");
return;
}
//setWaitScreen(true);
showProgressDialog();
Log.d(TAG, "Launching purchase flow for pro version purchase.");
mHelper.launchPurchaseFlow(
ProVersionActivity.this,
SKU_PRO_VERSION,
//IabHelper.ITEM_TYPE_SUBS,
RC_REQUEST,
mPurchaseFinishedListener,
mPayload);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
if (mHelper == null)
return;
// 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.");
}
}
private void setProversionPurchased(boolean value){
//temporarily allow the purchase immediately for development purposes.
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(ProVersionActivity.this);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putBoolean(SettingsActivity.PREF_KEY_PRO_VERSION, value);
editor.apply();
Toast.makeText(this,"Pro version purchased!",Toast.LENGTH_LONG).show();
}
private void complain(String message) {
Log.e(TAG, "Error: " + message);
alert("Error: " + message);
}
private void alert(String message) {
AlertDialog.Builder bld = new AlertDialog.Builder(this);
bld.setMessage(message);
bld.setNeutralButton("OK", null);
Log.d(TAG, "Showing alert dialog: " + message);
bld.create().show();
}
/** Verifies the developer payload of a purchase. */
private boolean verifyDeveloperPayload(Purchase p) {
mPayload = p.getDeveloperPayload();
Log.d(TAG, "payload: "+mPayload);
/*
* TODO: verify that the developer payload of the purchase is correct. It will be
* the same one that you sent when initiating the purchase.
*
* WARNING: Locally generating a random string when starting a purchase and
* verifying it here might seem like a good approach, but this will fail in the
* case where the user purchases an item on one device and then uses your app on
* a different device, because on the other device you will not have access to the
* random string you originally generated.
*
* So a good developer payload has these characteristics:
*
* 1. If two different users purchase an item, the payload is different between them,
* so that one user's purchase can't be replayed to another user.
*
* 2. The payload must be such that you can verify it even when the app wasn't the
* one who initiated the purchase flow (so that items purchased by the user on
* one device work on other devices owned by the user).
*
* Using your own server to store and verify developer payloads across app
* installations is recommended.
*/
return true;
}
/**
* Method to display registration progress dialog.
*/
private void showProgressDialog(){
/* Dismiss existing dialog if any. */
dismissProgressDialog();
new DialogAsyncTask().execute(new String[]{});
}
private void dismissProgressDialog(){
/*
if(mProgressDialog != null && mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
*/
RUN_PROGRESS_DIALOG = false;
}
public static boolean RUN_PROGRESS_DIALOG = true;
private class DialogAsyncTask extends AsyncTask<String,String,String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
@Override
protected String doInBackground(String... strings) {
while(RUN_PROGRESS_DIALOG){}
return null;
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
mProgressDialog.dismiss();
}
}
// We're being destroyed. It's important to dispose of the helper here!
@Override
public void onDestroy() {
super.onDestroy();
// very important:
Log.d(TAG, "Destroying helper.");
if (mHelper != null) {
mHelper.dispose();
mHelper = null;
}
}
}
The code keeps return -1005 response in which I couldn't find any reference from android developer site. I already spent countless of days finding the problems and googling please help me. Any comments and answers will be greatly appreciated. Thank you so much!
As @random indicated, you might need to clear your cache - see answers here: Android In App Billing - Error Retrieving Information From Server you might also want to look at:
Use The Right Keys: Android In App Billing - Error Retrieving Information From Server
Adding a list of alpha testers: https://support.google.com/googleplay/android-developer/answer/3131213?hl=en (from: https://stackoverflow.com/a/29926917)
These links might be helpful also:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With