Android 列表视图中的应用内计费工作流
我在Android应用程序中实现了应用内计费,有6款产品,它们就像用户为了在我的应用程序中购买物品而购买的硬币。 应用程序内的设置和测试工作完美我阅读了所有谷歌文档并按照他们说的做了,但我的问题是,我的产品显示在一个列表视图中,我称之为函数Android 列表视图中的应用内计费工作流,android,listview,in-app-purchase,in-app-billing,Android,Listview,In App Purchase,In App Billing,我在Android应用程序中实现了应用内计费,有6款产品,它们就像用户为了在我的应用程序中购买物品而购买的硬币。 应用程序内的设置和测试工作完美我阅读了所有谷歌文档并按照他们说的做了,但我的问题是,我的产品显示在一个列表视图中,我称之为函数mHelper。根据活动列表中的位置启动PurchaseFlow,但项目总是被消费或拥有这里是我的代码: IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelpe
mHelper。根据活动列表中的位置启动PurchaseFlow
,但项目总是被消费或拥有这里是我的代码:
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.");
}
};
以下是我对多重消费所做的
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);
把你的课改成这些
public class BankClass {
public int itemId;
public int quantity;
public String Price;
public BankClass(int _itemId,int _quantity,String _Price){
itemId = _itemId;
quantity = _quantity;
Price = _Price;
}
public int getItemId() {
return itemId;
}
public String getPrice() {
return Price;
}
public int getQuantity() {
return quantity;
}
}
在listitem中,单击更改这些代码,如bewlo
BankClass currentItem = BankList.get(position);
CoinItemID = currentItem.getItemId();
if (currentItem.getQuantity() == 100)
{
CoinItemID = currentItem.getItemId();
String payload = "";
mHelper.launchPurchaseFlow(BankActivity.this, SKU_hundred, RC_REQUEST,
mPurchaseFinishedListener, payload);
}
由于您正在消费多个项目,建议通过传递您的购买列表,使用ConsumeAncy for multiple items方法。您可以在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) {
/**
*与{@link consumatync}相同,但同时用于多个项目。
*@param PurchaseInfo对象列表,表示要消费的购买。
*@param listener消耗操作完成时要通知的侦听器。
*/
public void ConsumeAncync(列表购买,OnConsumeMultiFinishedListener侦听器){
使用onConsumeMultiFinished作为回调函数
public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);
public void onConsumemultimated(列出购买、列出结果);
它应该注意发送正确的异步消费请求。更新您的代码并发布任何问题。我想检查您的银行类,请发布该类的代码这里是银行类的代码,它与应用程序内的数据无关,只是为了在list@Dhawal Sodha ParmarCheck中显示数据。如果您还有问题,请告诉我你如何为列表项设置数据?我会这样做,但问题是在启动银行活动的开始,当我启动IabHelper.QueryInventoryFinishedListener mGotInventoryListener时,它立即崩溃,它说无法启动另一个异步,因为另一个尚未使用,并且我拥有所有的项目@Dhawal Sodha Parmarmake sure您正在使用应用内支付库的最新版本尝试以下解决方案:我已经在使用谷歌在其sdk最新版本中提供的相同代码,并且已经看到了这两个链接,这就是为什么我发布代码来检查我在这个过程中的工作流程中做错了什么?我是否在设置中遗漏了什么或做错了什么?这是更新了一个,因为问题是4天前提出的,我之前的代码在一些研究后有所不同,我的代码中的设置正确吗?我的代码中的查询正确吗?不知道为什么我总是会出现这个错误@Dhawal Sodha Parmar很抱歉延迟回复@random your right,但是我应该从inven更改我的代码吗tory每次查询调用ConsumeSync并给它一个列表,或者在最后我会调用它,因为我每次都在检查用户是否拥有它。你可以更具体地说,请如何在我的代码中使用它?当应用程序启动时,你需要调用ConsumeSync一次,并将其传递给它。你的购买列表和方法应该会处理好它。你可以检查我的edi吗ted请按照你的建议回答。你能发布你的崩溃日志吗?关于处理结果,你想做什么,你有一个购买清单,可以检查它是否被调用结果所占用。get(0)。isSuccess()当项目的索引为0时-您可以将其放入循环中。我今天也按照您的建议编辑了我的答案。请您看看我所做的是正确的还是错误的,每当我开始活动时,它会崩溃,并出现新代码和错误@random
/**
* 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) {
public void onConsumeMultiFinished(List<Purchase> purchases, List<IabResult> results);