Android в биллинге приложений: не удается запустить launchPurchaseFlow, так как выполняется launchPurchaseFlow
Я впервые использую 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'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.lang.IllegalStateException: Невозможно запустить асинхронную операцию (launchPurchaseFlow), потому что выполняется другая асинхронная операция (launchPurchaseFlow).
onActivityResult
обратный вызов не происходит, когда я пытаюсь совершить неудачную покупку, поэтому неудачный процесс запуска не обрабатывается и не очищается. Поэтому, когда я пытаюсь сделать еще одну покупку, именно поэтому она падает, потому что она все еще находится в середине последней неудачной транзакции.
Что я делаю неправильно? Как убедиться, что launchPurchaseFlow() очищен после сбоя?
6 ответов
Я полагаю, что вам просто нужно получить обновленный код классов биллинга в приложении, и вам больше не придется сталкиваться с той же проблемой.
Насколько я знаю, Google еще не внес изменения в SDK Manager. Просто скопируйте / вставьте новые классы в свой, и вы больше не столкнетесь с проблемой.
Ознакомьтесь с новыми изменениями кода здесь: 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
Я знаю, что это своего рода поздний вклад в этот вопрос, но я столкнулся с той же проблемой сегодня, и я вызывал биллинг в приложении внутри фрагмента, поэтому я посмотрел в "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);
}
Я надеюсь, что это поможет кому-то там...
Для меня лучшим решением было обновить код до последнего ( здесь) и сделать то, что предлагает этот пост:
1) сделать метод
flagEndAsync
общественности. Это там, просто не видно.2) иметь каждый вызов слушателя
iabHelper.flagEndAsync
убедиться, что процедура помечена как завершенная правильно; Кажется, это нужно всем слушателям.3) объемные звонки с
try/catch
пойматьIllegalStateException
что может произойти, и справиться с этим таким образом.
Причина, по которой обновление кода было недостаточно, заключается в том, что я обнаружил особые случаи, когда эта ошибка все еще возникает (или хотя бы одна):
- отключиться от интернета;
- введите ваше приложение;
- пусть он инициализирует
IabHelper
; - подключиться к Интернету;
- После подключения устройства попробуйте совершить покупку.
У меня та же проблема.
Первая попытка: обходной путь
Я скачал текущий IabHelper.java, согласно решению jmrmb80, но это не сработало. (Похоже, что сейчас репо устарело, и мы должны полагаться на версию, предоставленную менеджером Android SDK.) Поэтому я последовал совету Хана:
- определить IabHelper.flagEndAsync() как открытый и
- добавлять
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 отлично работает для меня.