【问题标题】:Libgdx and Google In-App-Purchase resultLibgdx 和 Google 应用内购买结果
【发布时间】:2013-12-09 01:57:26
【问题描述】:

我按照这些instructions 使用 ActionResolver 接口集成了 Libgdx 和本机 android 代码。我从代码的 Libgdx 部分调用 Android 方法没有问题。但是当我试图将 Google IAP 与 Libgdx 集成时,我遇到了死胡同。根据 TrivialDrive 示例,它使用 mPurchaseFinishedListener(在调用方法之外)。
我的问题是:由于侦听器在调用方法之外,如何将此 IAP 结果代码传递回 Libgdx?目前,购买过程已经完成,但我的代码的 libgdx 部分没有被“告知”购买状态/结果。
这是我的代码:

非常感谢任何帮助。

动作解析器:

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

【问题讨论】:

    标签: java android in-app-purchase libgdx


    【解决方案1】:

    您将无法从 requestIabPurchase() 返回结果 - 这样做的唯一方法会阻塞很长时间。在我看来,最好的方法是创建一个您自己的 LibGdx 项目实现的侦听器接口,并将其传递到您的请求接口中。例如:

    在你的 libGdx 项目中:

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

    动作解析器:

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

    请注意,您应该在 mPurchaseFinishedListener 有 return 的任何地方调用 PurchaseCallback.setPurchaseResult(),而不仅仅是在 // how do i pass this result to the libgdx? 行 - 否则,您永远不会知道购买是否失败或只是花费了很长时间。

    【讨论】:

    • 对,没想到。删除了我的答案。
    • 谢谢@logan-pikcup。我看到你指出。但是,我尝试了您的代码,似乎我的 PurchaseScreen 给了我这个错误The method requestIabPurchase(int, PurchaseCallback) in the type ActionResolver is not applicable for the arguments (int, new InputListener{})。 ecplise 1 Change method 'requestIabPurchase(int, PurchaseCallback)' to 'requestIabPurchase(int, InputLestener)' 建议的 2 个快速修复; 2Create method 'requestIabPurchase(int, InputLestener)' in type 'ActionResolver'。接下来我该怎么办?
    • 抱歉耽搁了 - 将 implements PurchaseCallback 添加到您传递给 requestIabPurchase 的类中(我假设您将 MainActivity 传递给 PurchaseCallback)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多