android - ListView 中的应用内结算工作流

标签 android listview in-app-purchase in-app-billing

我在 Android 应用程序中实现了应用程序内结算,有大约 6 种产品,它们就像用户为了在我的应用程序中购买商品而购买的硬币。 应用程序内的设置和测试工作完美我阅读了所有谷歌文档并按照他们说的做了但我的问题是我的产品显示在 ListView 中我根据在 Activity 列表中的位置,但项目总是被消耗或拥有这里是我的代码:

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 100 coins upgrade?
        Purchase hundrendCoin = inventory.getPurchase(SKU_hundred);
        if(hundrendCoin != null && verifyDeveloperPayload(hundrendCoin));
        {
            Log.d(TAG, "User have it ");
            mHelper.consumeAsync(inventory.getPurchase(SKU_hundred), mConsumeFinishedListener);
        }

        // Do we have the 225 coins upgrade?
        Purchase two_hundred_twenty_fiveCoin = inventory.getPurchase(SKU_two_hundred_twenty_five);
        if(two_hundred_twenty_fiveCoin != null && verifyDeveloperPayload(two_hundred_twenty_fiveCoin));
        {
            Log.d(TAG, "User have it ");
            mHelper.consumeAsync(inventory.getPurchase(SKU_two_hundred_twenty_five), mConsumeFinishedListener);
        }

        // Do we have the 350 coins upgrade?
        Purchase three_hundred_fiftyCoin = inventory.getPurchase(SKU_three_hundred_fifty);
        if(three_hundred_fiftyCoin != null && verifyDeveloperPayload(three_hundred_fiftyCoin));
        {
            Log.d(TAG, "User have it ");
            mHelper.consumeAsync(inventory.getPurchase(SKU_three_hundred_fifty), mConsumeFinishedListener);
        }

        // Do we have the 475 coins upgrade?
        Purchase four_hundred_seventy_fiveCoin = inventory.getPurchase(SKU_four_hundred_seventy_five);
        if(four_hundred_seventy_fiveCoin != null && verifyDeveloperPayload(four_hundred_seventy_fiveCoin));
        {
            Log.d(TAG, "User have it ");
            mHelper.consumeAsync(inventory.getPurchase(SKU_four_hundred_seventy_five), mConsumeFinishedListener);
        }

        // Do we have the 600 coins upgrade?
        Purchase six_hundredCoin = inventory.getPurchase(SKU_six_hundred);
        if(six_hundredCoin != null && verifyDeveloperPayload(six_hundredCoin));
        {
            Log.d(TAG, "User have it");
            mHelper.consumeAsync(inventory.getPurchase(SKU_six_hundred), mConsumeFinishedListener);
        }

        // Do we have the 1225 coins upgrade?
        Purchase one_thousand_two_hundred_twenty_fiveCoin = inventory.getPurchase(SKU_one_thousand_two_hundred_twenty_five);
        if(one_thousand_two_hundred_twenty_fiveCoin != null && verifyDeveloperPayload(one_thousand_two_hundred_twenty_fiveCoin));
        {
            Log.d(TAG, "User have it ");
            mHelper.consumeAsync(inventory.getPurchase(SKU_one_thousand_two_hundred_twenty_five), mConsumeFinishedListener);
        }

        mHelper.flagEndAsync();

        Log.d(TAG, "Initial inventory query finished; enabling main UI.");
    }
};
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                    BankClass currentItem = BankList.get(position);
                    CoinItemID = currentItem.itemID;
                    if (currentItem.quantity == 100)
                    {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_hundred, RC_REQUEST,
                                mPurchaseFinishedListener, payload);

                    } else if (currentItem.quantity == 225)
                    {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_two_hundred_twenty_five, RC_REQUEST,
                                mPurchaseFinishedListener, payload);

                    } else if (currentItem.quantity == 350) {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_three_hundred_fifty, RC_REQUEST,
                                mPurchaseFinishedListener, payload);
                    } else if (currentItem.quantity == 475) {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_four_hundred_seventy_five, RC_REQUEST,
                                mPurchaseFinishedListener, payload);

                    } else if (currentItem.quantity == 600) {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_six_hundred, RC_REQUEST,
                                mPurchaseFinishedListener, payload);

                    } else if (currentItem.quantity == 1225) {
                        CoinItemID = currentItem.itemID;
                        String payload = "";
                        mHelper.launchPurchaseFlow(BankActivity.this, SKU_one_thousand_two_hundred_twenty_five, RC_REQUEST,
                                mPurchaseFinishedListener, payload);

                    }
                }
            });
     @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.");
    }
}
boolean verifyDeveloperPayload(Purchase p)
{
    String payload = p.getDeveloperPayload();

    /*
     * 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;
}

// 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);

        // if we were disposed of in the meantime, quit.
        if (mHelper == null) return;

        if (result.isFailure())
        {
            complain("Error purchasing: " + result);
            return;
        }
        if (!verifyDeveloperPayload(purchase)) {
            complain("Error purchasing. Authenticity verification failed.");
            return;
        }

        Log.d(TAG, "Purchase successful.");

        if (purchase.getSku().equals(SKU_hundred)) {
            // bought 1/4 tank of gas. So consume it.
            Log.d(TAG, "Purchase is 100 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }
        else if (purchase.getSku().equals(SKU_two_hundred_twenty_five)) {
            Log.d(TAG, "Purchase is 225 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }
        else if (purchase.getSku().equals(SKU_three_hundred_fifty)) {
            Log.d(TAG, "Purchase is 350 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }
        else if (purchase.getSku().equals(SKU_four_hundred_seventy_five)) {
            Log.d(TAG, "Purchase is 475 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }
        else if (purchase.getSku().equals(SKU_six_hundred)) {
            Log.d(TAG, "Purchase is 600 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }
        else if (purchase.getSku().equals(SKU_one_thousand_two_hundred_twenty_five)) {
            Log.d(TAG, "Purchase is 1225 Coins. Starting consumption.");
            mHelper.consumeAsync(purchase, mConsumeFinishedListener);

        }

    }
};

// Called when consumption is complete
IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
    public void onConsumeFinished(Purchase purchase, IabResult result) {
        Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);

        // if we were disposed of in the meantime, quit.
        if (mHelper == null) return;

        // We know this is the "gas" sku because it's the only one we consume,
        // so we don't check which sku was consumed. If you have more than one
        // sku, you probably should check...
        if (result.isSuccess())
        {
            // successfully consumed, so we apply the effects of the item in our
            // game world's logic, which in our case means filling the gas tank a bit
            (new BuyCoinsTask()).execute();
            Log.d(TAG, "Consumption successful. Provisioning.");
        }
        else
        {
            complain("Error while consuming: " + result);
        }

        Log.d(TAG, "End consumption flow.");
    }
};

如有任何帮助,我们将不胜感激。

Bank 类:

public class BankClass
{
  public int itemID;
  public int quantity;
  public String price;
  public BankClass(int itemID,int quantity,String price)
  {
      this.itemID=itemID;
      this.quantity=quantity;
      this.price=price;
  }
}

这是我对多消费所做的。

List<Purchase> purchases = new ArrayList<>();
        purchases.add(inventory.getPurchase(SKU_hundred));
        purchases.add(inventory.getPurchase(SKU_two_hundred_twenty_five));
        purchases.add(inventory.getPurchase(SKU_three_hundred_fifty));
        purchases.add(inventory.getPurchase(SKU_four_hundred_seventy_five));
        purchases.add(inventory.getPurchase(SKU_six_hundred));
        purchases.add(inventory.getPurchase(SKU_one_thousand_two_hundred_twenty_five));

        IabHelper.OnConsumeMultiFinishedListener onCusumeListner = new IabHelper.OnConsumeMultiFinishedListener()
        {

            @Override
            public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results)
            {
                Log.d(TAG, "Consumption finished. Purchase: " + purchases + ", result: " + results);

                // if we were disposed of in the meantime, quit.
                if (mHelper == null) return;

                // We know this is the "gas" sku because it's the only one we consume,
                // so we don't check which sku was consumed. If you have more than one
                // sku, you probably should check...
                for(int i=0;i<results.size();i++)
                {
                    if (results.get(i).isSuccess())
                    {
                        // successfully consumed, so we apply the effects of the item in our
                        // game world's logic, which in our case means filling the gas tank a bit

                        Log.d(TAG, "Consumption successful. Provisioning.");
                    } else {
                        complain("Error while consuming: " + results);
                    }
                }
                Log.d(TAG, "End consumption flow.");
            }

        };
        mHelper.consumeAsync(purchases, onCusumeListner);

但结果我不知道如何根据那里的位置处理所有项目的结果是否成功,我应该为它运行 for 循环还是有另一种方法,但它仍然在所有方面崩溃。

Logcat 输出:

 04-17 13:01:31.083    8312-8964/net.httpiamheroic.herioc    E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-3333
  Process: net.httpiamheroic.herioc, PID: 8312
java.lang.NullPointerException: Attempt to read from field   'java.lang.String   net.httpiamheroic.herioc.net.httpiamherioc.util.Purchase.mItemType' on a   null object reference
        at   net.httpiamheroic.herioc.net.httpiamherioc.util.IabHelper.consume(IabHelper.java:660)
        at net.httpiamheroic.herioc.net.httpiamherioc.util.IabHelper$3.run(IabHelper.java:953)
        at java.lang.Thread.run(Thread.java:818)

最佳答案

由于您正在消费多个项目,因此建议通过传递您的购买列表来对多个项目使用 consumeAsync 方法。你可以在里面找到它 TrivialDrive Iab 版本 3 的示例应用程序

/**
 * Same as {@link consumeAsync}, but for multiple items at once.
 * @param purchases The list of PurchaseInfo objects representing the purchases to consume.
 * @param listener The listener to notify when the consumption operation finishes.
 */
public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {

使用 onConsumeMultiFinished 作为回调

public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);

它应该负责发送适当的异步消费请求。更新您的代码并发布任何问题。

关于android - ListView 中的应用内结算工作流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29422942/

相关文章:

android - 在 Android 的两个选项卡上使用相同的 View

android - 自定义列表的 AutoCompleteTextView 问题

ios - 执行应用内购买时发生 "Your request produced an error [new nullrespone]"

android - 如何获取项目中单元测试的数量

android - 使用 CoordinatorLayout 在 fragment 中隐藏 Activity 中的工具栏

android - 上下文菜单 onItemClick (ListView)

android - 广播接收器未注册

c# - VirtualizingTilePanel 背景滚动

ios - 如何在没有Mac的情况下启用应用内购买

iphone - iOS 7 警告中不推荐使用 transactionreceipt 的问题