webentwicklung-frage-antwort-db.com.de

Android In-App-Abrechnung: StartPurchaseFlow kann nicht gestartet werden, da LaunchPurchaseFlow ausgeführt wird

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?

36
Kenny Wyland

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

43
joelreeves

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 ...

29
alazmi95

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 auftretende IllegalStateException 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).

  • verbindung zum Internet trennen;
  • geben Sie Ihre App ein.
  • lass die IabHelper initialisieren;
  • mit dem Internet verbinden;
  • sobald das Gerät angeschlossen ist, versuchen Sie es zu kaufen.
10

Ich habe das gleiche Problem. 

Erster Versuch: Problemumgehung

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 :

  • definiere IabHelper.flagEndAsync () als public und
  • füge iabHelper.flagEndAsync() vor iabHelper.launchPurchaseFlow(...) hinzu

Dies scheint ein krasser Hack! Und es kann unerwünschte Nebenwirkungen haben. Aber es funktioniert "...".

Dies scheint ein bekannter Fehler zu sein: # 134 und # 189 .

Zweiter Versuch: Fix

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.

8
user2768

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.

2
RominaV

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.

0
Honza Musil