我已经设置了应用内结算,并且接口处理工作但是在发送launchPurchaseFlow之后立即触发PurchaseFinishedListener(在我选择购买之前)并返回-1002(IABHELPER_BAD_RESPONSE)
如果我继续点击购买进行购买。 PurchaseFinishedListener永远不会再次触发,但购买确实会通过,我可以通过运行queryInventoryAsync来验证它是否已经完成。这是我的代码。
public class InAppBilling {
private static final String TAG = "IAB";
static final String SKU_PREMIUM = "full_version";
// static final String ITEM_SKU = "android.test.purchased";
static final boolean DEBUG = true;
// Does the user have the premium upgrade?
public boolean mIsPremium = false;
// (arbitrary) request code for the purchase flow
static final int RC_REQUEST = 10001;
// The helper object
IabHelper mHelper;
Context context;
public InAppBilling(Context cntxt) {
this.context = cntxt;
inAppBillingInit();
}
private void inAppBillingInit()
{
// compute your public key and store it in base64EncodedPublicKey
String base64EncodedPublicKey = mykey;
mHelper = new IabHelper(context, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
@Override
public void onIabSetupFinished(IabResult result) {
if (!result.isSuccess()) {
// Oh noes, there was a problem.
Log.d(TAG, "Problem setting up In-app Billing: " + result);
}
// Hooray, IAB is fully set up!
// 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);
}
});
}
// Listener that's called when we finish querying the items and subscriptions we own
IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
@Override
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()) {
Log.d(TAG, "Failed to query inventory: " + result);
return;
}
if(inventory.hasPurchase(SKU_PREMIUM))
{
mHelper.consumeAsync(inventory.getPurchase(SKU_PREMIUM), new OnConsumeFinishedListener() {
@Override
public void onConsumeFinished(Purchase purchase, IabResult result) {
}
});
}
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 premium upgrade?
Purchase premiumPurchase = null;
// if(DEBUG)
// premiumPurchase = inventory.getPurchase(ITEM_SKU);
// else
premiumPurchase = inventory.getPurchase(SKU_PREMIUM);
if(premiumPurchase == null)
{
Toast.makeText(context.getApplicationContext(), "premiumPurchase = null", Toast.LENGTH_LONG).show();
}
else
{
int pstate = premiumPurchase.getPurchaseState(); // 0 (purchased), 1 (canceled), or 2 (refunded).
Toast.makeText(context.getApplicationContext(), "pstate = " + pstate, Toast.LENGTH_LONG).show();
}
mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase));
Log.d(TAG, "User is " + (mIsPremium ? "PREMIUM" : "NOT PREMIUM"));
if(mIsPremium) updateUi();
}
};
// Callback for when a purchase is finished
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
Toast.makeText(context.getApplicationContext(), "IAB_P_FinishedListener = " + result.getResponse(), Toast.LENGTH_LONG).show();
// if we were disposed of in the meantime, quit.
if (mHelper == null) return;
if (result.isFailure()) {
// complain("Error purchasing: " + result);
// setWaitScreen(false);
return;
}
// Don't complain if cancelling
if (result.getResponse() == IabHelper.IABHELPER_USER_CANCELLED) {
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification failed.");
// setWaitScreen(false);
return;
}
Log.d(TAG, "Purchase successful.");
if (purchase.getSku().equals(SKU_PREMIUM)) {
// bought the premium upgrade!
Log.d(TAG, "Purchase is premium upgrade. Congratulating user.");
alert("Thank you for upgrading to premium!");
mIsPremium = true;
updateUi();
// setWaitScreen(false);
}
}
};
void complain(String message) {
Log.e(TAG, "**** TrivialDrive Error: " + message);
alert("Error: " + message);
}
void alert(String message) {
AlertDialog.Builder bld = new AlertDialog.Builder(context);
bld.setMessage(message);
bld.setNeutralButton("OK", null);
Log.d(TAG, "Showing alert dialog: " + message);
bld.create().show();
}
/** Verifies the developer payload of a purchase. */
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
return true;
}
public void purchaseProVersion()
{
// disable_ad_kill = true;
// sendMessageToService(MSG_DISABLE, disable_ad_kill);
Log.d(TAG, "Upgrade button clicked; launching purchase flow for upgrade.");
// setWaitScreen(true);
/* TODO: for security, generate your payload here for verification. See the comments on
* verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use
* an empty string, but on a production app you should carefully generate this. */
String payload = "ProVersion";
//billingHelper.launchPurchaseFlow(this, sku, 123, this);
// if(DEBUG)
// mHelper.launchPurchaseFlow((Activity)context, ITEM_SKU, 123, mPurchaseFinishedListener);//, payload);
// else
mHelper.launchPurchaseFlow((Activity)context, SKU_PREMIUM, RC_REQUEST, mPurchaseFinishedListener, payload);
}
private void updateUi()
{
Sketch s = (Sketch) context;
if(mIsPremium) s.setToPro();
}
public void Destroy() {
// very important:
Log.d(TAG, "Destroying helper.");
if (mHelper != null) {
mHelper.dispose();
mHelper = null;
}
}
}
不确定是否重要但是这是来自调用puurchaseProVersion()的类的handleActivityResult。
@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
try {
if (!IAB.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...
Toast.makeText(this, "IAB.mHelper.handleActivityResult = false", Toast.LENGTH_LONG).show();
super.onActivityResult(requestCode, resultCode, data);
} else {
Log.d(TAG, "onActivityResult handled by IABUtil.");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}