Result of Libgdx and Google In-App-Purchase

I followed these instructions to integrate both Libgdx and native Android code using the ActionResolver interface. I have no problem calling the Android method from the libgdx part of my code. But I am at a dead end when I try to link Google IAP with Libgdx. According to the TrivialDrive example, it uses the mPurchaseFinishedListener (outside the invocation method).
My question is: how do I pass this IAP resultcode result back to Libgdx since the listener is outside the call method? Currently, the purchase process has passed, but part of the libgdx of my code is not "informed" about the status / result of the purchase.
This is my code:

Any help is greatly appreciated.

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 get an inventory of stuff we own. Log.d(TAG, "Setup successful. Querying inventory."); mHelper.queryInventoryAsync(mGotInventoryListener); } }); } // Listener that 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); 
+6
source share
1 answer

You cannot return the result from requestIabPurchase () - the only methods of this action will be blocked for a long time. The best way, in my opinion, would be to create your own listener interface that implements your LibGdx project and pass it to your request interface. For instance:

In your libGdx project somewhere:

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

ActionResolver:

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

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

... and pass everything that implements PurchaseCallback (I assume your PurchaseScreen does it yourself):

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

Finally, pin it to 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; } 

Note that you must call PurchaseCallback.setPurchaseResult () wherever mPurchaseFinishedListener has a return , not just on the line // how do i pass this result to the libgdx? - otherwise, you will never know that the purchase failed or simply takes a very long time.

+7
source

All Articles