2013-12-09 105 views
6

我遵循這些instructions以使用ActionResolver接口來集成Libgdx和本機android代碼。我從我的代碼的Libgdx部分調用Android方法沒有問題。但是當我試圖將Google IAP與Libgdx整合在一起時,我已經陷入死衚衕。根據TrivialDrive示例,它使用mPurchaseFinishedListener(調用方法之外)。
我的問題是:由於偵聽器在調用方法之外,我該如何將這個IAP結果碼傳遞迴Libgdx?目前,購買流程已經完成,但我的代碼的libgdx部分未被「通知」購買狀態/結果。
這是我的代碼:Libgdx和Google應用內購買結果

任何幫助,非常感謝。

ActionResolver:

public interface IActionResolver { 

public int requestIabPurchase(int product); 

} 

MainActivity:

public class MainActivity extends AndroidApplication implements IActionResolver { 

// Debug tag, for logging 
static final String TAG = "greatgame"; 

// Does the user have the premium upgrade? 
boolean mIsUpgraded = false; 

// SKUs for our products: the cat, all, or pow 
static final String SKU_UPGRADE = "android.test.purchased"; 

// (arbitrary) request code for the purchase flow 
static final int RC_REQUEST = 10001; 

// The helper object 
IabHelper mHelper; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration(); 
    cfg.useGL20 = false; 

    initialize(new Catland(this), cfg); 
} 

void iAbStartup() { 

    String base64EncodedPublicKey = "some key"; 

    // Create the helper, passing it our context and the public key to verify signatures with 
    Log.d(TAG, "Creating IAB helper."); 
    mHelper = new IabHelper(this, base64EncodedPublicKey); 

    // enable debug logging (for a production application, you should set this to false). 
    mHelper.enableDebugLogging(true); 

    // Start setup. This is asynchronous and the specified listener 
    // will be called once setup completes. 
    Log.d(TAG, "Starting setup."); 
    mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { 
     public void onIabSetupFinished(IabResult result) { 
      Log.d(TAG, "Setup finished."); 

      if (!result.isSuccess()) { 
       // Oh noes, there was a problem. 
       Log.d(TAG, "Problem setting up in-app billing: " + result); 
       return; 
      } 

      // Have we been disposed of in the meantime? If so, quit. 
      if (mHelper == null) { 
       return; 
      } 

      // IAB is fully set up. Now, let's get an inventory of stuff we own. 
      Log.d(TAG, "Setup successful. Querying inventory."); 
      mHelper.queryInventoryAsync(mGotInventoryListener); 
     } 
    }); 
} 

// Listener that's called when we finish querying the items and subscriptions we own 
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()) { 
      Log.d(TAG, "Failed to query inventory: " + result); 
      return; 
     } 

     Log.d(TAG, "Query inventory was successful."); 

     // Do we have the SKU_UPGRADE upgrade? 
     Purchase thisUpgrade = inventory.getPurchase(SKU_UPGRADE); 
     mIsUpgraded = (thisUpgrade != null && verifyDeveloperPayload(thisUpgrade)); 
     Log.d(TAG, "User is " + (mIsUpgraded ? "Upgraded" : "Free")); 
     Log.d(TAG, "Initial inventory query finished; enabling main UI."); 
     runPurchaseFlow(submitProduct); 
    } 
}; 

// Run real purchase flow 
public void runPurchaseFlow(int product) { 
    Log.d(TAG, "runPurchaseFlow"); 

    /* TODO: for security, generate your payload here for verification. See the comments on 
    *  verifyDeveloperPayload() for more info. Since this is a SAMPLE, we just use 
    *  an empty string, but on a production app you should carefully generate this. */ 
    String payload = ""; 

    if (product == 1) 
     mHelper.launchPurchaseFlow(this, SKU_UPGRADE, RC_REQUEST, mPurchaseFinishedListener, payload); 

} 

// 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()) { 
      Log.d(TAG, "Error purchasing: " + result); 
      return; 
     } 
     if (!verifyDeveloperPayload(purchase)) { 
      Log.d(TAG, "Error purchasing. Authenticity verification failed."); 
      return; 
     } 

     Log.d(TAG, "Purchase successful."); 

     if (purchase.getSku().equals(SKU_CAT)) { 
      // bought the upgrade! 
      Log.d(TAG, "Purchase Upgrade. Congratulating user."); 
      mIsUpgraded = true; 
    // how do i pass this result to the libgdx? 

     } 
    } 
}; 

/** Verifies the developer payload of a purchase. */ 
boolean verifyDeveloperPayload(Purchase p) { 
    String payload = p.getDeveloperPayload(); 
    return true; 
} 

@Override 
public int requestIabPurchase(int product) { 

    iAbStartup(); 

    return 0; // how do i get the result from mPurchaseFinishedListener? 
} 

} 

PurchaseScreen

result = greatgame.actionResolver.requestIabPurchase(1); 

回答

7

您將無法返回從requestIabPurchase()的結果 - 這樣做的唯一方法所以會阻止很長一段時間。在我看來,最好的方法是創建一個你自己的監聽器接口,讓你的LibGdx項目實現,並將其傳遞到你的請求接口中。例如:

在你libGdx項目的地方:

interface PurchaseCallback { 
    public int setPurchaseResult(int result); 
} 

ActionResolver:

public interface IActionResolver { 
    public int requestIabPurchase(int product, PurchaseCallback callback); 
} 

在PurchaseScreen,實現PurchaseCallback:

@override 
public int setPurchaseResult(int result) { 
    // Yay! I have a result from a purchase! Maybe you want a boolean instead of an int? I don't know. Maybe an int (for the product code) and a boolean. 
} 

...並通過無論是實施PurchaseCallback(我假設你的PurchaseScreen本身):

result = greatgame.actionResolver.requestIabPurchase(1, this); 

最後,勾了這一切在MainActivity:

PurchaseCallback mCallback = null; 

mPurchaseFinishedListener = ... etc. etc. 
. 
. 
. 
    if (mCallback != null) { 
     mCallback.setPurchaseResult(0); 
    } 
. 
. 
. 

@Override 
public int requestIabPurchase(int product, PurchaseCallback callback) { 
    mCallback = callback; // save this for later 

    iAbStartup(); 

    return 0; 
} 

請注意,您應該調用PurchaseCallback.setPurchaseResult()到處是mPurchaseFinishedListener有return,不僅在線路// how do i pass this result to the libgdx? - 否則,你會不知道購買是否失敗或者只是花了很長時間。

+0

對,沒想到那個。刪除了我的答案。 – Lestat

+0

謝謝@ logan-pikcup。我明白你的意思。然而,我嘗試了你的代碼,看起來我的PurchaseScreen給了我這個錯誤。類型ActionResolver中的方法requestIabPurchase(int,PurchaseCallback)不適用於參數(int,new InputListener {})。 ecplise 1'將方法'requestIabPurchase(int,PurchaseCallback)'改爲'requestIabPurchase(int,InputLestener)''; 2'在'ActionResolver'類型中創建方法'requestIabPurchase(int,InputLestener)'。接下來我應該做什麼? – Ziiiii

+1

對不起,延遲 - 將'ImplementsCallback'添加到傳遞給'requestIabPurchase'的類(我假設你將'MainActivity'傳遞給'PurchaseCallback')。 –