2

我终于弄清楚了如何在 InAppBilling API 的 v3 中使用 IAP。用户现在可以随心所欲地消费尽可能多的产品。

现在,我希望在确认购买完成后更新用户的 GUI。我已经在下面的代码中放置了 Toast 以尝试找出更新 GUI 的位置,但我还没有出现 Toast。但请记住,IAP 的消耗是有效的。

我在代码下方的代码中确定了为用户更新 GUI 的代码。那段代码是我想要在成功购买完成后运行的。

所以我的问题是将该代码片段放在哪里,以便在成功购买后为用户更新 GUI。

public class Levels extends SwarmActivity {

    //static final String SKU_BUYLIVES = "buy5lives";
    static final String SKU_BUYLIVES = "android.test.purchased";

    IabHelper mHelper;
    IInAppBillingService mService;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        moreLives = (Button)findViewById(R.id.moreLives);

        moreLives.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                buyLives();
            }
        });
     }

    public void buyLives() {

        final Dialog dialog = new Dialog(c);
        dialog.setContentView(R.layout.buylives);

        String base64EncodedPublicKey = a + b + d + e + f + g + h + i + j + k;

        TextView title = (TextView)dialog.findViewById(R.id.question);
        Button no = (Button)dialog.findViewById(R.id.no);
        Button yes = (Button)dialog.findViewById(R.id.yes);

        title.setText(c.getResources().getString(R.string.buyLivesQuestion));
        no.setText(c.getResources().getString(R.string.maybelater));
        yes.setText(c.getResources().getString(R.string.buy));

        // Create the helper, passing it our context and the public key to verify signatures with
        mHelper = new IabHelper(Levels.this, base64EncodedPublicKey);

        // start setup. this is asynchronous and the specified listener will be called once setup completes.
        mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
            public void onIabSetupFinished(IabResult result) {

                if (!result.isSuccess()) {
                    // there was a problem.
                    complain("An error has occurred.  We apologize for the inconvenience.    " + c.getResources().getString(R.string.problem1) + " " + result);
                    return;
                }

                // IAB is fully set up. Now, let's get an inventory of stuff we own.
                mHelper.queryInventoryAsync(mGotInventoryListener);                
            }
        });

        yes.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {                
                mHelper.launchPurchaseFlow(Levels.this, SKU_BUYLIVES, 10001, mPurchaseFinishedListener, "payload");
                dialog.dismiss();

// the below ~14 lines is the code that I want to call to update the GUI for the user.  this block of code has been all over the place.  this is just the last spot I tested it at.
                SharedPreferences settings = getSharedPreferences("level_SP", 0);
                livesCount = settings.getInt("livesTotal1", 0);
                remainderTimeStamp = settings.getLong("remainderTimeStamp1", 0);

                livesCount = 5;
                remainderTimeStamp = 0;

                SharedPreferences.Editor editor = settings.edit();
                editor.putInt("livesTotal1", livesCount);
                editor.putLong("remainderTimeStamp1", remainderTimeStamp);
                editor.commit();

                livesCountTV.setText(c.getResources().getString(R.string.livesCount) + "  " + livesCount);
                livesCounterTV.setText(c.getResources().getString(R.string.livesCounter) + "  FULL!");
            }
        });

        no.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                dialog.dismiss();
            }
        });
        dialog.show();
    }

    // listener that's called when we finish querying the items and subscriptions we own.
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            if(result.isFailure()) {

                complain(c.getResources().getString(R.string.sorryerror) + c.getResources().getString(R.string.failedtoquery) + " " + result);
                return;
            } else if(inventory.hasPurchase(SKU_BUYLIVES)) {
                mHelper.consumeAsync(inventory.getPurchase(SKU_BUYLIVES), null);
            }
        }
    };

    // callback for when a purchase is finished
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {

            // this appears to the user immediately after purchasing.
            if(result.isFailure()) {

                complain(c.getResources().getString(R.string.sorryerror) + result);

            } else if(purchase.getSku().equals(SKU_BUYLIVES)) {

                alert(c.getResources().getString(R.string.livesbought));

                try {
                    Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
                    int response = ownedItems.getInt("RESPONSE_CODE");

                    if (response == 0) {
                        // success
                        Toast.makeText(Levels.this, "SUCCESS", Toast.LENGTH_LONG).show();

                        try {
                            mService.consumePurchase(3, getPackageName(), SKU_BUYLIVES);

// this Toast is never seen.
                            Toast t = Toast.makeText(Levels.this, "PURCHASE CONSUMED", Toast.LENGTH_LONG);
                            t.setGravity(Gravity.CENTER, 0, 0);
                            t.show();
                        } catch (RemoteException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }                       
                    } else {
                        // error
// this Toast is never seen.
                        Toast.makeText(Levels.this, "ERROR", Toast.LENGTH_LONG).show();
                    }

                } catch (RemoteException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }       
            }
            return;
        }
    };

    void complain(String message) {
        alert("Error: " + message);
    }

    void alert(String message) {
        AlertDialog.Builder bld = new AlertDialog.Builder(this);
        bld.setMessage(message);
        bld.setNeutralButton("OK", null);
        bld.create().show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(mHelper != null) mHelper.dispose();
        mHelper = null;
    }
}
4

1 回答 1

1

要打开 Google Play 购买对话框,您应该使用startIntentSenderForResult()带有购买意图的方法。用户完成此对话框后,onActivityResult()将调用您的活动。如果需要,您应该在此处验证购买和更新 GUI。

这是您如何打开购买对话框的示例。

public void buyProduct() {
    PendingIntent buyIntent = ... // create your intent here
    IntentSender sender = buyIntent.getIntentSender();
    try {
        startIntentSenderForResult(sender, REQ_BUY_PRODUCT, new Intent(), 0, 0, 0);
    } catch (SendIntentException e) {
        Log.e(TAG, "", e);
    }
}

这是如何处理购买意图的示例

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQ_BUY_PRODUCT && resultCode == Activity.RESULT_OK) {
        // here you verify data intent and update your GUI
        ...
        return;
    }
}

这两种方法都属于您的活动。

于 2013-08-22T05:39:28.263 回答