App Billing v3 购买

App Billing v3 purchase

在我的测试应用程序中,用户单击购买按钮并购买了商品。购买完成后,文本视图会显示 "Purchase completed"。都好。 :).但是,当我终止该应用程序并再次打开它时,购买按钮再次出现......:/。为什么会这样? Google 这个不是很清楚。这是代码。

public class MainActivity extends Activity {

IInAppBillingService mService;
ServiceConnection connection;
String inappid = "victory.walkto.testingpaymentsd.productid"; //replace this with your in-app product id
Button purchaseBtn;
Button clickBtn;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
    serviceIntent.setPackage("com.android.vending");

    // first this
    connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;

        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IInAppBillingService.Stub.asInterface(service);
        }
    };

    // then this
    bindService(serviceIntent,connection, Context.BIND_AUTO_CREATE);

    purchaseBtn = (Button) findViewById(R.id.purchase);
    clickBtn = (Button) findViewById(R.id.clickButton);
    clickBtn.setVisibility(View.GONE);
    purchaseBtn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            ArrayList skuList = new ArrayList();
            skuList.add(inappid);
            Bundle querySkus = new Bundle();
            querySkus.putStringArrayList("ITEM_ID_LIST", skuList);
            Bundle skuDetails;


            try {
                Bundle ownedItems = mService.getPurchases(3,  
      getPackageName(), "inapp", null);
           // Check response
                int responseCode =  
      ownedItems.getInt("RESPONSE_CODE");
                if (responseCode != 0) {
                    throw new Exception("Error");
                }
     // Get the list of purchased items
                ArrayList<String> purchaseDataList =
                        ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
                for (String purchaseData : purchaseDataList) {
                    JSONObject o = new JSONObject(purchaseData);
                    String purchaseToken = o.optString("token", o.optString("purchaseToken"));
                    // Consume purchaseToken, handling any errors
                    mService.consumePurchase(3, getPackageName(), purchaseToken);
                }
                skuDetails = mService.getSkuDetails(3, getPackageName(),
                        "inapp", querySkus);

                int response = skuDetails.getInt("RESPONSE_CODE");
                if (response == 0) {

                    ArrayList<String> responseList = skuDetails
                            .getStringArrayList("DETAILS_LIST");

                    for (String thisResponse : responseList) {
                        JSONObject object = new JSONObject(thisResponse);
                        String sku = object.getString("productId");
                        String price = object.getString("price");
                        if (sku.equals(inappid)) {
                            System.out.println("price " + price);
                            Bundle buyIntentBundle = mService
                                    .getBuyIntent(3, getPackageName(), sku,
                                            "inapp",
                                            "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
                            PendingIntent pendingIntent = buyIntentBundle
                                    .getParcelable("BUY_INTENT");
                            startIntentSenderForResult(
                                    pendingIntent.getIntentSender(), 1001,
                                    new Intent(), Integer.valueOf(0),
                                    Integer.valueOf(0), Integer.valueOf(0));
                            purchaseBtn.setVisibility(View.GONE);

                            clickBtn.setOnClickListener(new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    Toast.makeText(getApplicationContext(),"I am clicked",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                }
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IntentSender.SendIntentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    });
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 1001) {
        String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");

        if (resultCode == RESULT_OK) {
            clickBtn.setVisibility(View.VISIBLE);
            try {
                JSONObject jo = new JSONObject(purchaseData);
                String sku = jo.getString(inappid);
                Toast.makeText(
                        MainActivity.this,
                        "You have bought the " + sku
                                + ". Excellent choice,adventurer!",
                        Toast.LENGTH_LONG).show();

            } catch (JSONException e) {
                System.out.println("Failed to parse purchase data.");
                e.printStackTrace();
            }
        }
    }
}
@Override
public void onDestroy() {
    super.onDestroy();
    if (connection != null) {
        unbindService(connection);
    }
  }
}

固定

IabHelper 中没有错误 Class。我必须将从 JSON 响应中获取的 orderId 值存储为 SharedPreference key/value 对。

类似这样。

SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            SharedPreferences.Editor editor = settings.edit();
            editor.putString("productId", sku);
            editor.putString("purchaseToken", purchaseToken);
            editor.putString("orderId", orderId);
            editor.commit();

检索它们。

SharedPreferences spreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
            productId = spreferences.getString("productId", "");
            purchaseToken = spreferences.getString("purchaseToken", "");
            orderId = spreferences.getString("orderId", "");

最后使用 if 条件使视图可见或不可见

if(orderId.isEmpty()) {


                entryFee.setVisibility(View.VISIBLE);
                paymentButton.setVisibility(View.VISIBLE);
                paymentText.setVisibility(View.VISIBLE);
                teamTextField.setVisibility(View.GONE);
                btn.setVisibility(View.GONE);
                paymentButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {


                        ArrayList skuList = new ArrayList();
                        skuList.add(inappid);
                        querySkus = new Bundle();
                        querySkus.putStringArrayList("ITEM_ID_LIST", skuList);

                        checkPayment();


                    }
                });
            }else{
                entryFee.setVisibility(View.GONE);
                paymentButton.setVisibility(View.GONE);
                paymentText.setVisibility(View.GONE);
                teamTextField.setVisibility(View.VISIBLE);
                btn.setVisibility(View.VISIBLE);
            }

解决方案并不难,但我必须通读大量文档,使用调试器点,仅此而已:)。

使您的代码不那么复杂。将嵌套的点击侦听器移到 oncreate 之外,并适当地命名这些方法。如果我是对的,你想做的是

onCreate:
    ## init listeners here
    ## then query purchase
    if purchased:
        hide purchase button
        show click button
    else:
        hide click button
        show purchase button

purchaseClickListener:
     make purchase
     if successfull:
        hide purchase button
        show click button

Read the documentation thoroughly before implementing

当您终止您的应用程序时,它会再次运行 onCeeate,从头开始设置。您需要检查是否适合在 onCreate 中显示您的按钮,方法是使用付款 Api 检查(如果可能)或将您的状态本地存储在 SharedPreference 中并检查。

您想为 IAP 尝试一些第 3 方库吗?我推荐使用这个库:OpenIAB。使用此库,您不仅可以在 Google Play Store 中进行 IAP,还可以在其他商店(Amazon store、Slide me...)中进行 IAP。查看更多详细信息。

这不容易破解,但我找到了所需的解决方法。最近对 Google 感到非常失望,他们的 Android 网站变得一团糟(很难找到有用的信息)并且他们的示例代码很差。几年前我在做一些 Android 开发时,一切都变得如此简单!这是另一个例子...

确实 IabUtil 有问题,它没有正确地取消它自己的异步任务。整套必要的解决方法来稳定这个东西:

1) 制作方法 flagEndAsync public。它就在那里,只是看不见。

2) 让每个侦听器调用 iabHelper.flagEndAsync 以确保程序正确标记为完成;似乎所有听众都需要它。

3) 用 try/catch 包围调用以捕获可能发生的 IllegalStateException,并以这种方式处理它。

下面的代码可以帮到你,

try {
     if (helper != null) {
             helper.flagEndAsync();
     }
     helper.launchPurchaseFlow(.....)
}catch(IllegalStateException e){
     e.printStackTrace();
}

我在这里发布答案,以供可能遇到相同问题的人使用。

您应该将来自 Google 服务器的 oprderId 和 transactionId 存储在共享首选项中。只有这样您的程序才会知道何时使购买按钮可见或不可见。

希望这会有所帮助。