Ich implementiere zum ersten Mal In App-Abrechnung und teste meine ersten Einkäufe mit den statischen SKU-IDs.
Es hat beim ersten Mal sehr gut funktioniert. Ich rief mHelper.launchPurchaseFlow(...)
an und schloss den Testkauf ab. Meine Aktivität hat den onActivityResult
Callback erhalten und ich habe sichergestellt, dass er mit mHelper.handleActivityResult(...)
verarbeitet wird. Alles war großartig.
@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);
}
}
Ich wollte jedoch den nächsten Teil testen, also habe ich die App erneut gestartet und versucht, dieselbe SKU (die statische purchased
-SKU) zu kaufen.
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");
Beim zweiten Versuch, den Artikel zu kaufen, wird meine OnIabPurchaseFinishedListener
aufgerufen, und in meinem Protokoll wird purchase failed
angezeigt: "Fehler bei In-App-Abrechnung: Artikel kann nicht gekauft werden.
Das macht Sinn, aber wenn ich versuche, einen anderen Artikel zu kaufen, stürzt meine App mit dem folgenden Fehler ab:
Java.lang.IllegalStateException: Async-Vorgang kann nicht gestartet werden (launchPurchaseFlow), weil ein weiterer Async Operation (launchPurchaseFlow) ist in Bearbeitung.
Der onActivityResult
-Callback tritt nicht auf, wenn ich versuche, den Kauf zu tätigen, der fehlschlägt. Der Startablauf, der fehlgeschlagen ist, wird also nicht behandelt und bereinigt. Wenn ich also einen anderen Kauf versuche, stürzt der Computer deshalb ab, weil er angeblich immer noch in der letzten fehlgeschlagenen Transaktion ist.
Was mache ich falsch? Wie kann ich sicherstellen, dass der launchPurchaseFlow () nach einem Fehler bereinigt wird?
Ich glaube, Sie müssen sich nur den aktualisierten Code der In-App-Abrechnungsklassen besorgen, und Sie sollten nicht erneut auf dasselbe Problem stoßen.
Soweit ich weiß, hat Google die Änderungen am SDK-Manager noch nicht veröffentlicht. Kopieren Sie einfach die neuen Klassen in Ihre, und Sie sollten nicht länger auf das Problem stoßen.
Sehen Sie sich die neuen Codeänderungen hier an: https://code.google.com/p/marketbilling/source/detail?r=7ec85a9b619fc5f85023bc8125e7e6b1ab4dd69f&path=/v3/src/com/exnd//de/drivialdrives/ Hauptaktivität.Java
Die Klassen, die seit dem 15. März geändert wurden, sind: IABHelper.Java, Inventory.Java, SkuDetails.Java und einige der MainActivity.Java-Dateien
Ich weiß, dass es sich um einen späten Beitrag zu der Frage handelt, aber heute stand ich vor demselben Problem und rief die In-App-Abrechnung innerhalb eines Fragments auf. Ich schaute in "labHelper.Java" und sah eine direkte Lösung, die ich glaube Das Problem ist ... Ich habe die Methode "void flagStartAsync (String-Operation)" in labHelper.Java so geändert, dass sie wie folgt aussieht
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);
}
Ich hoffe, das würde jemandem da draußen helfen ...
Für mich war die beste Lösung, sowohl den Code auf den letzten zu ändern ( hier ), als auch - diesen Beitrag vorzuschlagen:
1) Methode
flagEndAsync
öffentlich machen. Es ist da, nur nicht sichtbar.2) Lassen Sie jeden Listener
iabHelper.flagEndAsync
aufrufen, um sicherzustellen, dass die Prozedur ordnungsgemäß abgeschlossen ist. es scheint bei allen Zuhörern notwendig zu sein.3) Surround-Aufrufe mit einem
try/catch
, um die eventuell auftretendeIllegalStateException
abzufangen und auf diese Weise zu behandeln.
Der Grund dafür, dass die Aktualisierung des Codes nicht genug war, liegt darin, dass ich spezielle Fälle gefunden habe, in denen dieser Fehler immer noch auftritt (oder mindestens einer).
IabHelper
initialisieren;Ich habe das gleiche Problem.
Ich habe die aktuelle IabHelper.Java heruntergeladen, wie in jmrmb80s Lösung , aber das hat nicht funktioniert. (Es scheint, dass das Repo jetzt veraltet ist und wir sollten uns auf die vom Android SDK-Manager gelieferte Version verlassen.) Also folgte ich Khans Rat :
iabHelper.flagEndAsync()
vor iabHelper.launchPurchaseFlow(...)
hinzuDies scheint ein krasser Hack! Und es kann unerwünschte Nebenwirkungen haben. Aber es funktioniert "...".
Dies scheint ein bekannter Fehler zu sein: # 134 und # 189 .
Nach weiteren Untersuchungen glaube ich nicht, dass die obige Problemumgehung mein Problem gelöst hat. Ich denke, die echte Lösung soll onActivityResult
im UI-Thread überschreiben.
Keine Hacking-Lösungen erforderlich ..__ Die Aktivität oder das Fragment, die den Kaufablauf anfordert, sollten Folgendes aufweisen:
@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.");
}
}
Das ist von Googles Beispielprojekt, habe es bei meinem Projekt ausprobiert und es funktioniert.
Error response: 7:Item Already Owned
bedeutet, dass Sie einen Artikel gekauft haben, ihn aber noch nicht verbraucht haben und Sie versuchen, ihn erneut zu kaufen.
Dies ist mir passiert, als ich in AndroidManifest launchMode in meiner In-App-Aktivität auf singleInstance
eingestellt habe. Die App wurde immer mit dem von Ihnen beschriebenen Fehler beendet.
Um dieses Verhalten zu vermeiden, ändern Sie Ihren launchMode in einen anderen Wert, der Ihren Anforderungen entspricht Android:launchMode="singleInstance"
-> Android:launchMode="singleTask"
Ich habe nicht tief versucht zu verstehen, warum singleInstance nicht funktioniert. Wenn jemand weiß, geben Sie bitte weitere Informationen an.
Daher bestand meine Lösung darin, launchMode zu ändern und bereits im Besitz befindliche Artikel zu verwenden. Seit dieser Zeit funktioniert IAP gut für mich.