2013-12-09 21 views
6

Podążyłem za tymi instructions, aby zintegrować zarówno libgdx, jak i natywny kod androida za pomocą interfejsu ActionResolver. Nie mam problemu z wywołaniem metody Android z części libgdx mojego kodu. Ale próbuję zintegrować Google IAP z Libgdxem. Według przykładu TrivialDrive używa mPurchaseFinishedListener (poza metodą wywołania).
Moje pytanie brzmi: jak przekazać ten kod wyniku IAP z powrotem do Libgdx, ponieważ detektor jest poza metodą wywołującą? Obecnie trwa proces zakupu, ale część kodu libgdx mojego kodu nie jest "informowana" o statusie/wyniku zakupu.
To jest mój kod:Libgdx i Google In-App-Purchase result

Każda pomoc jest doceniana.

ActionResolver:

public interface IActionResolver { 

public int requestIabPurchase(int product); 

} 

główną działalność:

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

Odpowiedz

7

Nie będzie mógł powrócić wynik z requestIabPurchase() - jedyne metody prowadzenia blokowałoby to na długi czas. Najlepszym sposobem, moim zdaniem, byłoby stworzenie własnego interfejsu nasłuchiwania, który implementuje twój projekt LibGdx, i przekazanie go do interfejsu żądania. Na przykład:

W projekcie libgdx gdzieś:

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

ActionResolver:

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

W PurchaseScreen, wdrożyć 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. 
} 

... i przekazać cokolwiek wdraża PurchaseCallback (zakładam, że Twój PurchaseScreen robi to samo):

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

Wreszcie hak to wszystko w główną działalność:

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

Zauważ, że należy zadzwonić PurchaseCallback.setPurchaseResult() wszędzie że mPurchaseFinishedListener ma return, nie tylko na linii // how do i pass this result to the libgdx? - w przeciwnym razie, to będzie nigdy nie wiadomo, czy zakup się nie powiódł, czy zajmuje naprawdę dużo czasu.

+0

Dobrze, nie myślałem o tym. Usunąłem odpowiedź. – Lestat

+0

Dzięki @ logan-pikcup. Widzę, że wskazujesz. Próbowałem jednak twój kod, wydaje się, że mój PurchaseScreen dać mi ten błąd 'Metoda requestIabPurchase (int, PurchaseCallback) w typie ActionResolver nie ma zastosowania dla argumentów (int, new InputListener {})'. 2 szybkie poprawki sugerowane przez ecplise 1 "Zmień metodę" requestIabPurchase (int, PurchaseCallback) "na" requestIabPurchase (int, InputLestener) "; 2 "Utwórz metodę" requestIabPurchase (int, InputLestener) "w typie" ActionResolver''. Co powinienem zrobić dalej? – Ziiiii

+1

Przepraszamy za opóźnienie - dodaj 'implementuje PurchaseCallback' do klasy, którą przechodzisz do' requestIabPurchase' (Zakładam, że przekazywałeś 'MainActivity' do' PurchaseCallback'). –