2013-12-09 9 views
6

Ho seguito questi instructions per integrare sia il codice Android nativo che Libgdx utilizzando l'interfaccia ActionResolver. Non ho problemi a chiamare il metodo Android dalla parte Libgdx del mio codice. Ma sto colpendo un vicolo cieco quando sto cercando di integrare Google IAP con Libgdx. Secondo l'esempio TrivialDrive, utilizza mPurchaseFinishedListener (al di fuori del metodo di chiamata).
La mia domanda è: come faccio a passare questo codice risultato IAP a Libgdx poiché il listener è al di fuori del metodo di chiamata? Attualmente, il processo di acquisto è andato a buon fine, ma la parte libgdx del mio codice non viene "informata" dello stato/risultato dell'acquisto.
Questo è il mio codice:Risultato di acquisto in-app di Libgdx e Google

Qualsiasi aiuto è molto apprezzato.

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

risposta

7

Non sarà in grado di restituire il risultato da requestIabPurchase() - gli unici metodi di fare così bloccherebbe per molto tempo. Il modo migliore, a mio avviso, sarebbe quello di creare un'interfaccia listener che il tuo progetto LibGdx implementa e che passi all'interfaccia di richiesta. Per esempio:

Nel progetto libGdx da qualche parte:

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

ActionResolver:

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

In PurchaseScreen, implementare 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. 
} 

... e passare tutto ciò che sta attuando PurchaseCallback (presumo che lo stesso PurchaseScreen lo faccia):

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

Infine, collegare il tutto in 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; 
} 

noti che si dovrebbe chiamare PurchaseCallback.setPurchaseResult() in tutto il mondo che ha mPurchaseFinishedListener return, non solo alla linea // how do i pass this result to the libgdx? - in caso contrario, si vuole non so mai se un acquisto fallisce o richiede solo molto tempo.

+0

Giusto, non ci ho pensato. Cancellata la mia risposta. – Lestat

+0

Grazie @ logan-pikcup. Ti vedo punto. Ho provato il tuo codice tuttavia, sembra che il mio PurchaseScreen mi dia questo errore 'Il metodo requestIabPurchase (int, PurchaseCallback) nel tipo ActionResolver non è applicabile per gli argomenti (int, new InputListener {})'. le 2 soluzioni rapide suggerite da ecplise 1 'Cambia metodo 'requestIabPurchase (int, PurchaseCallback)' a 'requestIabPurchase (int, InputLestener)''; 2 'Crea metodo 'requestIabPurchase (int, InputLestener)' nel tipo 'ActionResolver''. Cosa dovrei fare dopo? – Ziiiii

+1

Ci scusiamo per il ritardo - aggiungere 'implementa PurchaseCallback' alla classe che stai passando a' requestIabPurchase' (supponevo che avessi passato 'MainActivity' a' PurchaseCallback'). –

Problemi correlati