Java 如何在Android应用程序中实现应用内计费?

Java 如何在Android应用程序中实现应用内计费?,java,android,in-app-billing,Java,Android,In App Billing,在Android应用程序中实现应用内计费似乎相当复杂。我怎么能这样做?SDK中的示例应用程序只有一个活动,对于像我这样有多个活动的应用程序来说,这有点过于简化了。好吧,我将尝试解释我的体验。我不认为自己是这方面的专家,但我几天就摔断了脑袋。p> 首先,我在试图理解示例和应用程序的工作流程时遇到了非常困难的情况。我认为最好从一个简单的示例开始,但是要将代码分成小块,并且不知道是否破坏了任何东西,这是非常困难的。我会告诉你我有什么,我从这个例子中改变了什么,使它工作 我有一个单一的活动,我所有的购买

在Android应用程序中实现应用内计费似乎相当复杂。我怎么能这样做?SDK中的示例应用程序只有一个活动,对于像我这样有多个活动的应用程序来说,这有点过于简化了。

好吧,我将尝试解释我的体验。我不认为自己是这方面的专家,但我几天就摔断了脑袋。p> 首先,我在试图理解示例和应用程序的工作流程时遇到了非常困难的情况。我认为最好从一个简单的示例开始,但是要将代码分成小块,并且不知道是否破坏了任何东西,这是非常困难的。我会告诉你我有什么,我从这个例子中改变了什么,使它工作

我有一个单一的活动,我所有的购买都来自于此。这叫专业

首先,您应该使用publicmarketdeveloper密钥更新安全类中的变量base64EncodedPublicKey,否则您将看到一个很好的异常

我将我的活动绑定到我的BillingService,如下所示:

      public class Pro extends TrackedActivity implements OnItemClickListener {

            private BillingService mBillingService;
            private BillingPurchaseObserver mBillingPurchaseObserver;
            private Handler mHandler;

            @Override
            protected void onCreate(Bundle savedInstanceState) {    
                super.onCreate(savedInstanceState);     
                setContentView(R.layout.pro);


                //Do my stuff

                mBillingService = new BillingService();
                mBillingService.setContext(getApplicationContext());

                mHandler = new Handler();
                mBillingPurchaseObserver = new BillingPurchaseObserver(mHandler);

            }

        }



    @Override
    protected void onStart() {
       //Register the observer to the service
        super.onStart();
        ResponseHandler.register(mBillingPurchaseObserver);   
    }


    @Override
    protected void onStop() {
        //Unregister the observer since you dont need anymore
        super.onStop();
        ResponseHandler.unregister(mBillingPurchaseObserver);
    }

    @Override
    protected void onDestroy() {
       //Unbind the service
        super.onDestroy();
        mBillingService.unbind();
    }
这样,所有的购买都会与此服务进行通信,然后将JSON请求发送到市场。您可能认为购买是在同一时间完成的,但不是。您发送请求后,购买可能会在几分钟或几小时后完成。我认为这主要是因为服务器过载和信用卡审批

然后,我有一个包含我的物品的列表视图,并在每个物品上打开一个AlertDialog,邀请他们购买物品。当他们单击某个项目时,我会执行以下操作:

  private class BuyButton implements DialogInterface.OnClickListener {

       private BillingItem item = null;
       private String developerPayload;

       public BuyButton(BillingItem item, String developerPayload) {
        this.item = item;
        this.developerPayload = developerPayload;
        }

            @Override
            public void onClick(DialogInterface dialog, int which) {

                if (GeneralHelper.isOnline(getApplicationContext())){
                    //I track the buy here with GA SDK. 

        mBillingService.requestPurchase(this.item.getSku(), this.developerPayload);             
                } else {                
                    Toast.makeText(getApplicationContext(), R.string.msg_not_online, Toast.LENGTH_SHORT).show();
                }

            }

        }
好的,你应该看到市场开放,用户要么完成,要么取消购买

然后重要的是我的PurChaseObserver,它处理市场发送的所有事件。这是它的一个精简版本,但您应该明白这一点(通过代码查看我的注释):

我相信你不需要编辑任何其他内容。代码的其余部分“起作用”。 您可以首先在自己的项目“android.test.purchased”中尝试使用示例SKU。到目前为止,我已经测试了这一点,它的工作,但我仍然需要涵盖一切,如退款状态。在这种情况下,我允许用户保留这些功能,但我希望在修改之前确保其工作完美


我希望它能帮助你和其他人

如果你想使用一个简单的库在Google Play和Amazon Appstore上发布,你可以使用。它将两者的细节抽象到一个易于使用的库中。详细说明见Github页面。

V3:以下是快速入门教程。。他正在使用google示例中的helper类(普通驱动器)。。。就像第一个“你好”一样


这里提供了一个完整的Android应用内计费示例v3,并附有屏幕截图。请查看教程:

希望这会有帮助

有关更多说明,请阅读本教程:

在我们的项目中集成应用内计费库需要遵循的步骤

更新您的AndroidManifest.xml文件

创建ServiceConnection并将其绑定到IInapplingService

从应用程序向IInAppBillingService发送应用内计费请求

处理来自Google Play的应用内账单响应

更新AndroidManifest.xml

<uses-permission android:name="com.android.vending.BILLING" />
InAppPurchaseActivity.java和app\u purchase.xml中的activity\u

这将为我们的应用程序用户提供进行应用程序内购买的机会。在布局文件中,我们将为用户提供以不同面额购买的机会

InAppPurchaseActivity.java

public class Helper {
    public static final String ITEM_ID_LIST = "ITEM_ID_LIST";
    public static final String ITEM_ONE_ID = "productone";
    public static final String ITEM_TWO_ID = "producttwo";
    public static final String ITEM_THREE_ID = "productthree";
    public static final int RESPONSE_CODE = 1001;
    public static final String SHARED_PREF = "shared_pref";
    public static final String DEVELOPER_PAYLOAD = "developer_payload";
    public static final String PURCHASE_TOKEN = "purchase_token";
    public static void displayMessage(Context context, String message){
        Toast.makeText(context.getApplicationContext(), message, Toast.LENGTH_LONG).show();
    }
}
注意:应在非UI线程中调用getAllUserPurchase()和itemPurchaseAvailability()方法,以避免应用程序崩溃

public class InAppPurchaseActivity extends AppCompatActivity {
    private static final String TAG = InAppPurchaseActivity.class.getSimpleName();
    private IInAppBillingService mService;
    private CustomSharedPreference customSharedPreference;
    String[] productIds = new String[]{Helper.ITEM_ONE_ID, Helper.ITEM_TWO_ID, Helper.ITEM_THREE_ID};
    private ImageView buyOneButton, buyTwoButton, buyThreeButton;
    private static final char[] symbols = new char[36];
    static {
        for (int idx = 0; idx < 10; ++idx)
            symbols[idx] = (char) ('0' + idx);
        for (int idx = 10; idx < 36; ++idx)
            symbols[idx] = (char) ('a' + idx - 10);
    }
    private String appPackageName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_in_app_purchase);
        appPackageName = this.getPackageName();
        Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
        serviceIntent.setPackage("com.android.vending");
        bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
        customSharedPreference = new CustomSharedPreference(InAppPurchaseActivity.this);
        buyOneButton = (ImageView)findViewById(R.id.buy_one);
        buyOneButton.setVisibility(View.GONE);
        assert buyOneButton != null;
        buyOneButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_ONE_ID);
            }
        });
        buyTwoButton = (ImageView)findViewById(R.id.buy_two);
        buyTwoButton.setVisibility(View.GONE);
        assert buyTwoButton != null;
        buyTwoButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_TWO_ID);
            }
        });
        buyThreeButton = (ImageView)findViewById(R.id.buy_three);
        buyThreeButton.setVisibility(View.GONE);
        assert buyThreeButton != null;
        buyThreeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(!isBillingSupported()){
                    Helper.displayMessage(InAppPurchaseActivity.this, getString(R.string.in_app_support));
                    return;
                }
                purchaseItem(Helper.ITEM_THREE_ID);
            }
        });
    }
    ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IInAppBillingService.Stub.asInterface(service);
            AvailablePurchaseAsyncTask mAsyncTask = new AvailablePurchaseAsyncTask(appPackageName);
            mAsyncTask.execute();
        }
    };
    private void purchaseItem(String sku){
        String generatedPayload = getPayLoad();
        customSharedPreference.setDeveloperPayLoad(generatedPayload);
        try {
            Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), sku, "inapp", generatedPayload);
            PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
            try {
                startIntentSenderForResult(pendingIntent.getIntentSender(), Helper.RESPONSE_CODE, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == Helper.RESPONSE_CODE) {
            int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
            String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
            String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
            if (resultCode == RESULT_OK) {
                try {
                    JSONObject purchaseJsonObject = new JSONObject(purchaseData);
                    String sku = purchaseJsonObject.getString("productId");
                    String developerPayload = purchaseJsonObject.getString("developerPayload");
                    String purchaseToken = purchaseJsonObject.getString("purchaseToken");
                    //the developerPayload value is better stored in remote database but in this tutorial
                    //we will use a shared preference
                    for(int i = 0; i < productIds.length; i++){
                        if(productIds[i].equals(sku) && developerPayload.equals(customSharedPreference.getDeveloperPayload())){
                            customSharedPreference.setPurchaseToken(purchaseToken);
                            //access to private content
                            Intent contentIntent = new Intent(InAppPurchaseActivity.this, PrivateContentActivity.class);
                            startActivity(contentIntent);
                        }
                    }
                }
                catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    private String getPayLoad(){
        RandomString randomString = new RandomString(36);
        String payload = randomString.nextString();
        return payload;
    }
    public class RandomString {
        private final Random random = new Random();
        private final char[] buf;
        public RandomString(int length) {
            if (length < 1)
                throw new IllegalArgumentException("length < 1: " + length);
            buf = new char[length];
        }
        public String nextString() {
            for (int idx = 0; idx < buf.length; ++idx)
                buf[idx] = symbols[random.nextInt(symbols.length)];
            return new String(buf);
        }
    }
    public final class SessionIdentifierGenerator {
        private SecureRandom random = new SecureRandom();
        public String nextSessionId() {
            return new BigInteger(130, random).toString(32);
        }
    }
    private class AvailablePurchaseAsyncTask extends AsyncTask<Void, Void, Bundle> {
        String packageName;
        public AvailablePurchaseAsyncTask(String packageName){
            this.packageName = packageName;
        }
        @Override
        protected Bundle doInBackground(Void... voids) {
            ArrayList<String> skuList = new ArrayList<String>();
            skuList.add(Helper.ITEM_ONE_ID);
            skuList.add(Helper.ITEM_TWO_ID);
            skuList.add(Helper.ITEM_THREE_ID);
            Bundle query = new Bundle();
            query.putStringArrayList(Helper.ITEM_ID_LIST, skuList);
            Bundle skuDetails = null;
            try {
                skuDetails = mService.getSkuDetails(3, packageName, "inapp", query);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            return skuDetails;
        }
        @Override
        protected void onPostExecute(Bundle skuDetails) {
            List<AvailablePurchase> canPurchase = new ArrayList<AvailablePurchase>();
            int response = skuDetails.getInt("RESPONSE_CODE");
            if (response == 0) {
                ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
                if(responseList != null){
                    for (String thisResponse : responseList) {
                        JSONObject object = null;
                        try {
                            object = new JSONObject(thisResponse);
                            String sku = object.getString("productId");
                            String price = object.getString("price");
                            canPurchase.add(new AvailablePurchase(sku, price));
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[0])){
                buyOneButton.setVisibility(View.VISIBLE);
            }else{
                buyOneButton.setVisibility(View.GONE);
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[1])){
                buyTwoButton.setVisibility(View.VISIBLE);
            }else{
                buyTwoButton.setVisibility(View.GONE);
            }
            if(checkIfPurchaseIsAvailable(canPurchase, productIds[2])){
                buyThreeButton.setVisibility(View.VISIBLE);
            }else{
                buyThreeButton.setVisibility(View.GONE);
            }
        }
    }
    @org.jetbrains.annotations.Contract("null, _ -> false")
    private boolean checkIfPurchaseIsAvailable(List<AvailablePurchase> all, String productId){
        if(all == null){ return false;}
        for(int i = 0; i < all.size(); i++){
            if(all.get(i).getSku().equals(productId)){
                return true;
            }
        }
        return false;
    }
    public boolean isBillingSupported(){
        int response = 1;
        try {
            response = mService.isBillingSupported(3, getPackageName(), "inapp");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        if(response > 0){
            return false;
        }
        return true;
    }
    public void consumePurchaseItem(String purchaseToken){
        try {
            int response = mService.consumePurchase(3, getPackageName(), purchaseToken);
            if(response != 0){
                return;
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    public Bundle getAllUserPurchase(){
        Bundle ownedItems = null;
        try {
            ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return ownedItems;
    }
    public List<UserPurchaseItems> extractAllUserPurchase(Bundle ownedItems){
        List<UserPurchaseItems> mUserItems = new ArrayList<UserPurchaseItems>();
        int response = ownedItems.getInt("RESPONSE_CODE");
        if (response == 0) {
            ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
            ArrayList<String>  purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
            ArrayList<String>  signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
            String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
            if(purchaseDataList != null){
                for (int i = 0; i < purchaseDataList.size(); ++i) {
                    String purchaseData = purchaseDataList.get(i);
                    assert signatureList != null;
                    String signature = signatureList.get(i);
                    assert ownedSkus != null;
                    String sku = ownedSkus.get(i);
                    UserPurchaseItems allItems = new UserPurchaseItems(sku, purchaseData, signature);
                    mUserItems.add(allItems);
                }
            }
        }
        return mUserItems;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mService != null) {
            unbindService(mServiceConn);
        }
    }
}
测试应用内付费购买

  • 创建Google+帐户(不使用主帐户)
  • 添加将在您的组或社区中测试应用程序的用户
  • 应用内购买测试期间可能遇到的错误

    您要求的商品无法购买

    解决方案–

    他的一切功劳都归于他


    Android开发者博客还推荐了一个关于销售应用内产品的培训课程。要查看完整的实现并了解如何测试该应用程序,请查看本教程:

    好的,这是其中一个没有太多在线文档可供使用的内容,因此我将尽力一步一步地解释所有内容。摘自我的博客文章,这是一个更详细的版本(带有截图)。毫无疑问

    第一步:权限 这是最简单的一步。导航到manifest.xml文件,并在标记下添加以下行:

    <uses-permission android:name="com.android.vending.BILLING" />
    
    现在我们将使用一个名为mHelper的对象,我们将使用它完成所有操作

    base64EncodedPublicKey = ""; //PUT YOUR BASE64KEY HERE
    
    mHelper = new IabHelper(this, base64EncodedPublicKey);
    mHelper.enableDebugLogging(false); //set to false in real app
    
    
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
        public void onIabSetupFinished(IabResult result) {
            if (!result.isSuccess()) {
                // Oh no, there was a problem.
    
                if (result.getResponse() == 3) {
                    new AlertDialog.Builder(MainActivity.this)
                            .setTitle("In app billing")
                            .setMessage("This device is not compatible with In App Billing, so" +
                                    " you may not be able to buy the premium version on your phone. ")
                            .setPositiveButton("Okay", null)
                            .show();
                }
    
                Log.v(TAG, "Problem setting up In-app Billing: " + result);
            } else {
                Log.v(TAG, "YAY, in app billing set up! " + result);
                try {
                    mHelper.queryInventoryAsync(mGotInventoryListener); //Getting inventory of purchases and assigning listener
                } catch (IabHelper.IabAsyncInProgressException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    
    好吧,让我来解释一下这里发生了什么。基本上,我们调用“startSetup”来初始化“IabHelper”。如果安装成功,我们将查询用户已经购买了什么,并将响应存储在
    mGotInventoryListener
    中,接下来我们将对其进行编码:

    IabHelper.QueryInventoryFinishedListener mGotInventoryListener
            = new IabHelper.QueryInventoryFinishedListener() {
        public void onQueryInventoryFinished(IabResult result,
                                             Inventory inventory) {
    
            i = inventory;
    
            if (result.isFailure()) {
                // handle error here
    
                Log.v(TAG, "failure in checking if user has purchases");
            } else {
                // does the user have the premium upgrade?
                if (inventory.hasPurchase("premium_version")) {
    
                    premiumEditor.putBoolean("hasPremium", true);
                    premiumEditor.commit(); 
    
                    Log.v(TAG, "Has purchase, saving in storage");
    
                } else {
    
                    premiumEditor.putBoolean("hasPremium", false);
                    premiumEditor.commit();
    
                    Log.v(TAG, "Doesn't have purchase, saving in storage");
    
                }
            }
        }
    };
    
    上面的代码非常简单。基本上,它只是检查用户已经购买了什么。既然我们知道用户是否已经购买了我们的产品,我们就知道是否应该要求他们购买我们的产品!如果他们以前从未购买过我们的产品,让我们开始购买请求:

    public void buyPremium() {
        try {
    
         mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
         mHelper.launchPurchaseFlow(this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"); //Making purchase request and attaching listener
        } catch (Exception e) {
            e.printStackTrace();
    
    mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
    
    
    
    
            new AlertDialog.Builder(MainActivity.this)
                    .setTitle("Error")
                    .setMessage("An error occurred in buying the premium version. Please try again.")
                    .setPositiveButton("Okay", null)
                    .show();
        }
    }
    
    
        @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
    
        if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
    
        }
    
        else 
            Log.d(TAG, "onActivityResult handled by IABUtil.");
        }
    
    }
    
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
            = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
    
            Log.v(TAG, "purchase finished");
    
            if (purchase != null) {
    
                if (purchase.getSku().equals("premium_version")) {
    
                    Toast.makeText(MainActivity.this, "Purchase successful!", Toast.LENGTH_SHORT).show();
    
                    premiumEditor.putBoolean("hasPremium", true);
                    premiumEditor.commit();
                }
            } else {
                return;
            }
            if (result.isFailure()) {
                return;
            }
        }
    };
    
    在这里,我们通过以下方式购买项目(使用我们先前在play console中生成的ID):

     mHelper.launchPurchaseFlow(this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"); //Making purchase request and attaching listener
    
    请注意,我们将
    mppurchasefinishedlistener
    传递到参数中。这意味着购买的结果将返回到此侦听器。然后,我们只需检查购买是否为空,如果不是,则奖励用户购买的任何功能

    别让听众泄密!我们必须在应用程序销毁时销毁它们

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mHelper != null)
            try {
                mHelper.dispose();
                mHelper = null;
    
            } catch (IabHelper.IabAsyncInProgressException e) {
                e.printStackTrace();
            }
    }
    
    最后,如果你想消费你购买的东西
    public void buyPremium() {
        try {
    
         mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
         mHelper.launchPurchaseFlow(this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"); //Making purchase request and attaching listener
        } catch (Exception e) {
            e.printStackTrace();
    
    mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
    
    
    
    
            new AlertDialog.Builder(MainActivity.this)
                    .setTitle("Error")
                    .setMessage("An error occurred in buying the premium version. Please try again.")
                    .setPositiveButton("Okay", null)
                    .show();
        }
    }
    
    
        @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
    
        if (!mHelper.handleActivityResult(requestCode, resultCode, data)) {
    
        }
    
        else 
            Log.d(TAG, "onActivityResult handled by IABUtil.");
        }
    
    }
    
    IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener
            = new IabHelper.OnIabPurchaseFinishedListener() {
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
    
            Log.v(TAG, "purchase finished");
    
            if (purchase != null) {
    
                if (purchase.getSku().equals("premium_version")) {
    
                    Toast.makeText(MainActivity.this, "Purchase successful!", Toast.LENGTH_SHORT).show();
    
                    premiumEditor.putBoolean("hasPremium", true);
                    premiumEditor.commit();
                }
            } else {
                return;
            }
            if (result.isFailure()) {
                return;
            }
        }
    };
    
     mHelper.launchPurchaseFlow(this, "premium_version", 9, mPurchaseFinishedListener, "SECURITYSTRING"); //Making purchase request and attaching listener
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mHelper != null)
            try {
                mHelper.dispose();
                mHelper = null;
    
            } catch (IabHelper.IabAsyncInProgressException e) {
                e.printStackTrace();
            }
    }
    
    public void consume(){
    
        //MAKING A QUERY TO GET AN ACCURATE INVENTORY
        try {
            mHelper.flagEndAsync(); //If any async is going, make sure we have it stop eventually
    
            mHelper.queryInventoryAsync(mGotInventoryListener); //Getting inventory of purchases and assigning listener
    
            if(i.getPurchase("gas")==null){
                Toast.makeText(this, "Already consumed!", Toast.LENGTH_SHORT).show();
            }
        } catch (IabHelper.IabAsyncInProgressException e) {
            e.printStackTrace();
    
            Toast.makeText(this, "Error, try again", Toast.LENGTH_SHORT).show();
            mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
        }
    
        //ACTUALLY CONSUMING
        try {
            mHelper.flagEndAsync();//If any async is going, make sure we have it stop eventually
    
            this.mHelper.consumeAsync(this.i.getPurchase("gas"), new IabHelper.OnConsumeFinishedListener() {
                public void onConsumeFinished(Purchase paramAnonymousPurchase, IabResult paramAnonymousIabResult) {
    //resell the gas to them
                }
            });
    
            return;
        } catch (IabHelper.IabAsyncInProgressException localIabAsyncInProgressException) {
            localIabAsyncInProgressException.printStackTrace();
            Toast.makeText(this, "ASYNC IN PROGRESS ALREADY!!!!" +localIabAsyncInProgressException, Toast.LENGTH_LONG).show();
            Log.v("myTag", "ASYNC IN PROGRESS ALREADY!!!");
    
            mHelper.flagEndAsync();
        }
    }