Google In-App结算导致异常

cle*_*vor 3 eclipse in-app-billing google-play

在我的一个Android应用中,我正在尝试从Google的应用内结算中轻松获取广告资源,但它一直在给我错误

mHelper.queryInventoryAsync(mGotInventoryListener);
Run Code Online (Sandbox Code Playgroud)

随着消息

IabHelper没有设置.无法执行操作:queryInventory

这是所有IabHelper代码.

    mHelper = new IabHelper(this, base64EncodedPublicKey);
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
           public void onIabSetupFinished(IabResult result) {
              if (!result.isSuccess()) {
                 // Oh noes, there was a problem.
                 Log.d(TAG, "Problem setting up In-app Billing: " + result);
              }            
                 // Hooray, IAB is fully set up!  
           }
        });
    //check to see if ads have been removed(bought)
    IabHelper.QueryInventoryFinishedListener mGotInventoryListener 
       = new IabHelper.QueryInventoryFinishedListener() {
       public void onQueryInventoryFinished(IabResult result,
          Inventory inventory) {

          if (result.isFailure()) {
            // handle error here
          }
          else {
            // does the user have the premium upgrade?
            if(inventory.hasPurchase(REMOVE_ADS)) removeAdsPurchased = true;     
            // update UI accordingly
          }
       }
    };
    mHelper.queryInventoryAsync(mGotInventoryListener);
Run Code Online (Sandbox Code Playgroud)

Car*_*arl 9

简短的回答是,您的queryInventoryAsync()调用应该在您的onIabSetupFinished()方法内部进行.这是一个异步调用,因此您不能继续使用IabHelper实例,直到调用该回调告诉您帮助程序与计费服务的通信已建立.您的代码目前的编写方式,您有竞争条件,您的queryInventoryAsync()调用将赢得该竞赛并尝试在设置之前使用IabHelper对象,这是导致问题的原因.

此外,依赖于此对象的UI处理程序中的任何其他代码(例如,启动购买的按钮的处理程序)应测试完全设置的IabHelper对象,并且不应允许用户使用该UI元素,直到在onCreate()中创建的IabHelper实例已成功完成设置.处理这种情况的最简单方法是简单地禁用此类UI元素,直到调用安装程序回调以指示安装已成功完成.

这是容易的部分.当您运行onCreate()方法后立即发生的操作(即,不在用户的控制下),需要使用完全设置的IabHelper实例时,会出现更严重的问题.这通常是由于活动生命周期调用而发生的 - 特别是onResume()(如果有些东西需要IabHelper实例,每次你的应用程序到达前台时都必须这样做,而不仅仅是在调用onCreate()时),最值得注意的是,在onActivityResult()中(当用户完成或中止与计费界面的交互时调用 - 例如,作为进行应用内付款的一部分).

问题是操作系统可能会停止您的应用程序(例如,当用户启动购买时为计费界面腾出空间),导致您的IabHelper实例与您的应用程序一起销毁,并且该实例必须是下次调用onCreate()时会重新生成,并且会再次在onCreate()中启动安装程序,并且在对该对象执行任何其他操作之前,您需要再次等待安装完成.

可能发生这种情况的一个值得注意的情况是在用户与计费界面的交互期间作为购买过程的一部分.该交互的结果将通过onActivityResult()传递给您的应用程序,onActivityResult()本身需要使用完全设置的IabHelper对象,因此如果您的应用程序在用户与计费服务进行交互时从内存中刷新(或取消)购买,然后onActivityResult()必须等待IabHelper实例再次设置(在它可以使用之前在onCreate()中重新创建之后.

处理此问题的一种方法是设置并发布到需要IabHelper实例的待处理操作队列,onResume()和/或onActivityResult()代码添加到该队列,并使用onIabSetupFinished()方法处理该队列一次IabHelper设置(由onCreate()启动)已完成.

这不是微不足道的.上次我检查时,TrivialDrive示例应用程序没有处理上述情况.

测试此类用例的最佳方法是使用开发人员选项"不要保持活动",这会导致每次用户离开时都会销毁您的应用程序,以模拟操作系统在需要回收时将执行的操作内存,以便您可以确保您的应用程序在这些条件下工作.