Android в биллинге приложений: не удается запустить launchPurchaseFlow, потому что выполняется launchPurchaseFlow

я реализую в биллинге приложений в первый раз, и я тестирую свои первые покупки, используя статические идентификаторы SKU.

это сработало очень хорошо в первый раз. Я позвал!--2--> и завершается проверочной закупки. Моя деятельность получила onActivityResult обратный вызов, и я убедился, чтобы обработать его с mHelper.handleActivityResult(...). Все было замечательно.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Pass on the activity result to the helper for handling
    log("onActivityResult");
    if (!this.mHelper.handleActivityResult(requestCode, resultCode, data)) {
        log("cleared the launch flow");
        // not handled, so handle it ourselves (here's where you'd
        // perform any handling of activity results not related to in-app
        // billing...
        super.onActivityResult(requestCode, resultCode, data);
    }
}

однако я хотел протестировать следующую часть, поэтому я перезапустил приложение и попытался купить тот же SKU (статический purchased SKU).

mHelper.launchPurchaseFlow(rootActivity, "android.test.purchased", 10002,   
       new IabHelper.OnIabPurchaseFinishedListener() {

        @Override
        public void onIabPurchaseFinished(IabResult result, Purchase purchaseInfo) {
            if (result.isFailure()) {
                log("purchased failed");
            } else {
                log("purchase succeeded");
            }
        }
    }, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");

второй раз, когда я пытаюсь купить товар, мой OnIabPurchaseFinishedListener называется и вижу purchase failed в моем журнале: "ошибка выставления счетов в приложении: невозможно купить товар, ответ на ошибку: 7: товар уже принадлежит"

это имеет смысл, но если я попытаюсь купить другой элемент, то мое приложение вылетает со следующей ошибкой:

java.ленг.IllegalStateException: не удается запустить асинхронную операцию (launchPurchaseFlow) потому что другой асинхронный операция (launchPurchaseFlow) является в процессе.

на onActivityResult обратный вызов не происходит, когда я пытаюсь сделать покупку, которая терпит неудачу, поэтому поток запуска, который потерпел неудачу, не обрабатывается и не очищается. Поэтому, когда я пробую другую покупку, она падает, потому что она все еще предположительно находится в середине последней неудачной транзакции.

что я делаю не так? Как убедиться, что launchPurchaseFlow() очищается после сбоя?

6 ответов


Я считаю, что вам просто нужно получить обновленный код классов биллинга в приложении, и вы не должны снова столкнуться с той же проблемой.

Google еще не вытолкнул изменения в Диспетчере SDK, насколько я знаю. Просто скопируйте / вставьте новые классы в свой, и вы больше не должны сталкиваться с проблемой.

посмотрите на новые изменения кода здесь: https://code.google.com/p/marketbilling/source/detail?r=7ec85a9b619fc5f85023bc8125e7e6b1ab4dd69f&path=/v3/src/com/example/android/trivialdrivesample/MainActivity.java

классы, которые были изменены по состоянию на 15 марта: IABHelper.java, инвентарь.java, SkuDetails.java и некоторые из MainActivity.файл java


Я знаю, что это своего рода поздний вклад в вопрос, но сегодня я столкнулся с той же проблемой, и я звонил в приложение биллинга в фрагменте, поэтому я посмотрел в "labHelper.java", и я видел прямое решение, которое я считаю проблемой, которая есть ... Я изменил метод "void flagStartAsync (String operation)" в labHelper.java должен быть следующим

void flagStartAsync(String operation) {
    if (mAsyncInProgress) {
        flagEndAsync();
    }
    if (mAsyncInProgress) throw new IllegalStateException("Can't start async operation (" +
            operation + ") because another async operation(" + mAsyncOperation + ") is in progress.");
    mAsyncOperation = operation;
    mAsyncInProgress = true;
    logDebug("Starting async operation: " + operation);
}

Я надеюсь, что это поможет кому-то там ...


для меня лучшим решением было как udpate код к недавнему (здесь), и делать, что этот пост предлагаем:

1) Сделать метод flagEndAsync общественности. Она есть, просто не видно.

2) у каждого слушателя называть iabHelper.flagEndAsync чтобы убедиться, что процедура отмечена правильно; кажется, это необходимо во всех слушателях.

3) объемные вызовы с try/catch поймать IllegalStateException что может произойти, и обработать его таким образом.

причина, по которой обновление кода было недостаточно, заключается в том, что я нашел особые случаи, когда эта ошибка все еще происходит (или, по крайней мере, один):

  • отключение от сети Интернет;
  • введите ваши приложения;
  • пусть он инициализирует IabHelper;
  • подключение к интернету;
  • после подключения устройства попробуйте совершить покупку.

у меня такая же проблема.

первая попытка: обходной путь

Я скачал ток IabHelper.java, согласно jmrmb80 это, но это не сработало. (Похоже, что РЕПО сейчас устаревший и мы должны полагаться на версию, поставляемую Android SDK manager.) Поэтому я последовал совет Хана:

  • определить IabHelper.flagEndAsync() как public, и
  • добавить iabHelper.flagEndAsync() до iabHelper.launchPurchaseFlow(...)

Это похоже на откровенную халтуру! И это может иметь нежелательные побочные эффекты. Но это "работает"...

Это, кажется, известная ошибка: #134 и #189.

вторая попытка: исправление

после дальнейшего расследования, я не думаю, что приведенное выше решение решить мою проблему. Я думаю, что реальное решение - переопределение onActivityResult в потоке пользовательского интерфейса.


Не нужно богатство решений. Действие или фрагмент, запрашивающий поток покупки, должен иметь следующее:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data);
    if (billingHelper == null) return;

    // Pass on the activity result to the helper for handling
    if (!billingHelper.handleActivityResult(requestCode, resultCode, data)) {
        // not handled, so handle it ourselves (here's where you'd
        // perform any handling of activity results not related to in-app
        // billing...
        super.onActivityResult(requestCode, resultCode, data);
    }
    else {
        Log.d(TAG, "onActivityResult handled by IABUtil.");
    }
}

Это из примера проекта Google, попробовал его на моем проекте, и он работает.


Error response: 7:Item Already Owned означает, что вы купили товар, но вы еще не потребляли его, и вы пытаетесь купить его снова.

Это случилось со мной, когда я установил в AndroidManifest launchMode в моей активности в приложении к singleInstance. Приложение всегда заканчивается с ошибкой, которую вы описали.

чтобы избежать такого поведения, измените launchMode на любое другое значение, соответствующее вашим потребностям android:launchMode="singleInstance" ->android:launchMode="singleTask"

Я не пытался глубоко понять, почему singleInstance не работает. Если кто-то знает пожалуйста, предоставьте больше информации.

поэтому моим решением было изменить launchMode и потреблять уже принадлежащий элемент. С тех пор IAP отлично работает для меня.