Я внедряю In App Billing в первый раз, и я тестирую свои первые покупки, используя статические идентификаторы SKU.
Это сработало очень хорошо в первый раз. Я позвонил mHelper.launchPurchaseFlow(...)
и завершил пробную покупку. Моя активность получила обратный вызов 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 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.lang.IllegalStateException: не удается запустить асинхронную работу (launchPurchaseFlow), потому что другой асинхронный выполняется операция (launchPurchaseFlow).
Обратный вызов onActivityResult
не происходит, когда я пытаюсь выполнить покупку, которая терпит неудачу, поэтому сбой при запуске не обрабатывается и не очищается. Поэтому, когда я пытаюсь выполнить другую покупку, это происходит потому, что она все еще предположительно находится в середине последней неудавшейся транзакции.
Что я делаю неправильно? Как я могу убедиться, что startPurchaseFlow() очищен после сбоя?
Ответ 1
Я считаю, что вам просто нужно получить обновленный код в классах биллинга в приложении, и вам не следует снова запускать ту же проблему.
Google пока не опубликовал изменения в диспетчере SDK, насколько я знаю. Просто скопируйте/вставьте новые классы в свои, и вам больше не придется сталкиваться с проблемой.
Посмотрите на новые изменения кода здесь:
https://code.google.com/p/marketbilling/source/detail?r=7ec85a9b619fc5f85023bc8125e7e6b1ab4dd69f&path=/v3/src/com/example/android/trivialdrivesample/MainActivity.java
Классы, которые были изменены с 15 марта: IABHelper.java, Inventory.java, SkuDetails.java и некоторые файлы MainActivity.java
Ответ 2
Я знаю, что это довольно поздний вклад в вопрос, но сегодня я столкнулся с одной и той же проблемой, и я звонил в биллинг приложений внутри фрагмента, поэтому я посмотрел в "labHelper.java", и я увидел прямое решение Я верю в проблему, которая...
Я изменил метод "void flagStartAsync (Строковая операция)" в 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);
}
Я надеюсь, что это поможет кому-то...
Ответ 3
Для меня лучше всего было исправить код до недавнего ( здесь) и выполните этот пост:
1) сделать метод flagEndAsync
общедоступным. Это там, просто не видно.
2) имеют каждый вызов слушателя iabHelper.flagEndAsync
, чтобы удостовериться, что процедура отмечена правильно; это кажется необходимым во всех слушателях.
3) объединить вызовы с помощью try/catch
, чтобы поймать IllegalStateException
, который может произойти, и обрабатывать его таким образом.
Причина, по которой обновление кода было недостаточным, заключается в том, что я обнаружил особые случаи, когда эта ошибка все еще встречается (или хотя бы одна):
- отключиться от Интернета;
- введите ваше приложение;
- пусть инициализирует
IabHelper
;
- подключиться к Интернету;
- После подключения устройства попробуйте сделать покупку.
Ответ 4
У меня та же проблема.
Первая попытка: Временное решение
Я загрузил текущий IabHelper.java, согласно
jmrmb80 решение, но это не сработало. (Кажется, что репо теперь устарело, и мы должны полагаться на версию, предоставленную менеджером Android SDK.) Поэтому я последовал за ханский совет:
- определить IabHelper.flagEndAsync() как общедоступный и
- добавить
iabHelper.flagEndAsync()
до iabHelper.launchPurchaseFlow(...)
Это похоже на вопиющий взлом! И это может иметь нежелательные побочные эффекты. Но он "работает"...
Это, кажется, известная ошибка: # 134 и # 189.
Вторая попытка: Fix
После дальнейшего расследования, я не думаю, что описанное выше решение помогло решить мою проблему. Я думаю, что реальное решение должно переопределить onActivityResult
в потоке пользовательского интерфейса.
Ответ 5
Нет необходимости в хакерских решениях.
Действие или фрагмент, запрашивающий поток покупки, должен иметь следующее:
@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 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 образца, попробовал его в моем проекте, и он работает.
Ответ 6
Error response: 7:Item Already Owned
означает, что вы купили предмет, но вы его еще не потребляли, и вы пытаетесь его снова купить.
Это случилось со мной, когда я установил в AndroidManifest launchMode в своей активности в приложении в singleInstance
. Приложение всегда заканчивается ошибкой, которую вы описали.
Чтобы избежать такого поведения, измените свой режим запуска на любое другое значение, которое соответствует вашим потребностям
android:launchMode="singleInstance"
→ android:launchMode="singleTask"
Я не пытался понять, почему singleInstance не работает. Если кто-то знает, пожалуйста, предоставьте дополнительную информацию.
Итак, мое решение состояло в том, чтобы изменить startMode и использовать уже принадлежащий ему элемент. С тех пор IAP отлично работает для меня.