问题描述
我按照这些 说明 使用集成 Libgdx 和本机 android 代码动作解析器接口.我从代码的 Libgdx 部分调用 Android 方法没有问题.但是当我尝试将 Google IAP 与 Libgdx 集成时,我遇到了死胡同.根据 TrivialDrive 示例,它使用 mPurchaseFinishedListener(在调用方法之外).
我的问题是:由于侦听器在调用方法之外,如何将此 IAP 结果代码传递回 Libgdx?目前,购买过程已经完成,但我的代码的 libgdx 部分没有被告知"购买状态/结果.
这是我的代码:
I followed these instructions to integrate both Libgdx and native android code using ActionResolver interface. I have no problem calling the Android method from the Libgdx part of my code. But I am hitting a dead end when I am trying to intergrate Google IAP with Libgdx. According to TrivialDrive example, it uses mPurchaseFinishedListener (outside of calling method).
My question is: how do I pass this IAP resultcode back to Libgdx since the listener is outside the calling method? Currently, purchase process went through, but the libgdx part of my code is not being "informed" of the purchase status/result.
This is my code:
非常感谢任何帮助.
动作解析器:
public interface IActionResolver {
public int requestIabPurchase(int product);
}
主活动:
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?
}
}
购买屏幕
result = greatgame.actionResolver.requestIabPurchase(1);
推荐答案
您将无法从 requestIabPurchase() 返回结果 - 这样做的唯一方法会阻塞很长时间.在我看来,最好的方法是创建一个您自己的 LibGdx 项目实现的侦听器接口,并将其传递到您的请求接口中.例如:
You won't be able to return the result from requestIabPurchase() - the only methods of doing so would block for a long time. The best way, in my opinion, would be to create a listener interface of your own that your LibGdx project implements, and pass that into your request interface. For example:
在你的 libGdx 项目中:
In your libGdx project somewhere:
interface PurchaseCallback {
public int setPurchaseResult(int result);
}
动作解析器:
public interface IActionResolver {
public int requestIabPurchase(int product, PurchaseCallback callback);
}
在 PurchaseScreen 中,实现 PurchaseCallback:
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.
}
...并传递实现 PurchaseCallback 的任何内容(我假设您的 PurchaseScreen 自己执行):
...and pass whatever is implementing PurchaseCallback (I'm assuming your PurchaseScreen does itself):
result = greatgame.actionResolver.requestIabPurchase(1, this);
最后,将它们全部连接到 MainActivity:
Finally, hook it all up 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;
}
请注意,您应该在 mPurchaseFinishedListener 有 return
的任何地方调用 PurchaseCallback.setPurchaseResult(),而不仅仅是在 //我如何将此结果传递给 libgdx?
- 否则,您永远不会知道购买是否失败或只是花费了很长时间.
Note that you should call PurchaseCallback.setPurchaseResult() everywhere that mPurchaseFinishedListener has return
, not only at the line // how do i pass this result to the libgdx?
- otherwise, you will never know if a purchase failed or is just taking a really long time.
这篇关于Libgdx 和 Google 应用内购买结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!