2013-07-30 16 views
3

在我的Android應用程序之一,我想實現從谷歌的應用內結算清單的一個簡單的搶,但它一直給我的錯誤在谷歌應用內結算,導致異常

mHelper.queryInventoryAsync(mGotInventoryListener); 

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); 
+1

請問這個問題給你一些燈光:http:// stackoverflow.com/questions/13943950/in-app-billing-doesnt-work-iab-helper-is-not-set-up? – Raptor

回答

9

簡短的回答是您的queryInventoryAsync()調用應該從onIabSetupFinished()方法中進行。這是一個異步調用,因此您不能繼續使用IabHelper實例,直到該回調已被調用,以告訴您助理與賬單服務的通信已建立。您的代碼現在寫入的方式,您有競爭條件,並且您的queryInventoryAsync()調用將贏得該比賽,並嘗試在設置之前使用IabHelper對象,這是造成問題的原因。

此外,依賴此對象的UI處理程序(例如,啓動購買的按鈕的處理程序)中的任何其他代碼都應該測試完全設置的IabHelper對象,並且不應允許用戶使用該對象UI元素,直到在onCreate()中創建的IabHelper實例已成功完成設置。處理這種情況的最簡單方法是簡單地禁用這些UI元素,直到調用設置回調以指示設置已成功完成。

這是很容易的部分。當您的onCreate()方法運行後立即發生的操作(即,不在用戶的控制之下),需要使用完全設置的IabHelper實例時,會出現更嚴重的問題。這通常是由於活動生命週期調用 - 特別是onResume()(如果有什麼需要IabHelper實例,每當您的應用程序到達前臺時必須完成的,而不是在調用onCreate()時調用,只是)尤其是在onActivityResult()中(當用戶完成或中止與計費界面的交互時(例如,作爲進行應用程序內支付的一部分)時調用)。

問題是您的應用程序可能被操作系統阻止(例如,當用戶啓動購買時爲計費界面本身騰出空間),導致您的IabHelper實例與應用程序一起銷燬,並且該實例將在下次調用onCreate()時重新生成,並且將再次在onCreate()中啓動安裝程序,並且再次使用該對象之前需要等待安裝程序完成。

這可能發生的一個值得注意的情況是在用戶與計費接口交互作爲購買過程的一部分期間。該交互的結果將通過onActivityResult()傳遞給您的應用程序,該應用程序本身需要使用完全設置的IabHelper對象,所以如果您的應用程序在用戶與結算服務進行交互時從內存中刷新,或取消)購買,那麼onActivityResult()將不得不等待IabHelper實例再次設置(在onCreate()中重新創建之後才能使用它)。

處理此問題的一種方法是設置併發布到需要IabHelper實例的待處理操作隊列中,並且將onResume()和/或onActivityResult()代碼添加到該隊列中,並使用onIabSetupFinished()方法處理該隊列onCreate())已完成。

這不是微不足道的。上次我查了一下,TrivialDrive示例應用程序沒有處理上述情況。

測試這種用例的最好方法是使用開發人員選項「不要保留活動」,這會導致您的應用程序在用戶每次離開時被銷燬,以模擬操作系統將在什麼時候執行操作它需要回收內存,以便您可以確保您的應用在這些條件下正常工作。

+0

這是一個驚人的迴應。我只有4個月進入Android開發,所以我不太瞭解所有的東西,但我會努力讓我的應用程序啓動並運行。 –

+0

即使您正在做正確的事,如果您使用隨SDK一起發佈的示例代碼,也會發生此錯誤。這個特定的錯誤已在官方市場計費git repo中得到修復:https://code.google.com/p/marketbilling/source/checkout – 2013-12-15 00:32:29

+0

是的,我也注意到TrivialDrive演示已經修復,但還沒有嘗試過它,因爲我已經解決了我自己的應用程序中的問題。 – Carl

0

偉大的東西來自卡爾。我「認爲」我看到了類似的事情,但我的應用程序是通過崩潰:

java.lang.IllegalStateException: IabHelper was disposed of, so it cannot be used. 

它我的情況下,旋轉設備的一種方式,然後馬上回到原來的方向有時會導致此故障。似乎有一個「可能」發生崩潰的時間「窗口」(由於IAB的異步性質,如Carl解釋)。

我修復

我的「修復」是使mHelper靜態的,只有對其進行實例化if (mHelper == null),並沒有摧毀它在活動的的onDestroy()方法。這樣,一旦安裝完成,它就會一直存在,並且不需要擔心異步操作(由設備方向導致)。

不知道這是否是正確的修復,但認爲我會提及它,以防它幫助別人。

+0

當然,如果Android殺死你的進程,那麼靜態mHelper將被重置爲null,並且你會檢測到它並創建一個新的IabHelper對象來分配給它,而如果Android沒有動作或者只有它殺死你的活動,那麼mHelper將保持完整。 在方向更改的情況下,Android將只重新啓動正在運行的活動,這可能是您之前處理mHelper的代碼導致上面報告的錯誤的原因(因爲mHelper引用了處置的對象)。 也可以自己處理方向更改。 – Carl

-1

只需使checkNotDisposed()方法同步並且問題消失。這是因爲它有時被稱爲單獨的線程,並不總是具有mDisposed的最新值,它可能已在主線程中設置:

private synchronized void checkNotDisposed()