J'implémente In App Billing pour la première fois et je teste mes premiers achats à l'aide des identifiants de SKU statiques.
Cela a très bien fonctionné la première fois. J'ai appelé mHelper.launchPurchaseFlow(...)
et terminé l'achat du test. Mon activité a reçu le rappel onActivityResult
et je me suis assuré de le traiter avec mHelper.handleActivityResult(...)
. Tout était super.
@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);
}
}
Cependant, je voulais tester la partie suivante, j'ai donc relancé l'application et essayé d'acheter le même SKU (le statique 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");
La deuxième fois que j'essaie d'acheter l'article, ma OnIabPurchaseFinishedListener
est appelée et je vois purchase failed
dans mon journal: "Erreur de facturation intégrée à l'application: impossible d'acheter un article, réponse d'erreur: 7: article déjà en possession"
Cela a du sens, mais si j'essaie d'acheter un autre article, mon application se bloque avec l'erreur suivante:
Java.lang.IllegalStateException: impossible de démarrer l'opération asynchrone (launchPurchaseFlow) car un autre asynchrone opération (launchPurchaseFlow) est en cours.
Le rappel onActivityResult
ne se produit pas lorsque j'essaie de faire un achat qui échoue. Le flux de lancement qui a échoué n'est ni traité ni nettoyé. Ainsi, lorsque j'essaye un autre achat, c'est la raison pour laquelle il se bloque car il est censé être encore au milieu de la dernière transaction ayant échoué.
Qu'est-ce que je fais mal? Comment puis-je m'assurer que la commande launchPurchaseFlow () est nettoyée après une défaillance?
Je sais que c'est un peu une contribution tardive à la question, mais je faisais face au même problème aujourd'hui et j'appelais la facturation intégrée à l'application dans un fragment. J'ai donc cherché dans "labHelper.Java" et j'ai trouvé une solution directe qui, je le crois le problème qui est ... J'ai modifié la méthode "void flagStartAsync (String operation)" dans labHelper.Java pour ressembler à ceci
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);
}
J'espère que cela aiderait quelqu'un là-bas ...
Pour moi, la meilleure solution consistait à mettre à jour le code à la version récente ( here ) et à faire ce que this post
1) rendre la méthode
flagEndAsync
publique. C'est là, mais pas visible.2) demandez à chaque auditeur d’appeler
iabHelper.flagEndAsync
pour s’assurer que la procédure est correctement marquée; il semble être nécessaire chez tous les auditeurs.3) entourez les appels avec un
try/catch
pour intercepter laIllegalStateException
qui peut survenir, et gérez-le de cette façon.
La raison pour laquelle la mise à jour du code n'était pas suffisante, c'est que j'ai trouvé des cas particuliers où ce bogue se produit toujours (ou au moins un):
IabHelper
;J'ai le même problème.
J'ai téléchargé la version actuelle de IabHelper.Java , conformément à la solution de jmrmb80 , mais cela n'a pas fonctionné. (Il semble que le dépôt soit maintenant deprecated et que nous devrions nous fier à la version fournie par le gestionnaire de SDK Android.) J'ai donc suivi le conseil de Khan :
iabHelper.flagEndAsync()
avant iabHelper.launchPurchaseFlow(...)
Cela ressemble à un bidouillage flagrant! Et cela peut avoir des effets secondaires indésirables. Mais, il fonctionne"...
Cela semble être un bogue connu: # 134 et # 189 .
Après une enquête plus approfondie, je ne pense pas que la solution ci-dessus résout mon problème. Je pense que la solution real consiste à remplacer onActivityResult
dans le fil de l'interface utilisateur.
Pas besoin de solutions de hackers ... L'activité ou le fragment qui demande le flux d'achat doit avoir ceci:
@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.");
}
}
Cela provient de l'exemple de projet de Google, essayé sur mon projet et cela fonctionne.
Error response: 7:Item Already Owned
signifie que vous avez acheté un article mais que vous ne l'avez pas encore consommé et que vous essayez de l'acheter à nouveau.
Cela m'est arrivé lorsque j'ai activé AndroidManifest launchMode dans mon activité in-app à singleInstance
. App toujours fini avec l'erreur que vous avez décrite.
Pour éviter ce problème, modifiez votre launchMode sur toute autre valeur adaptée à vos besoins Android:launchMode="singleInstance"
-> Android:launchMode="singleTask"
Je n'ai pas essayé de comprendre profondément pourquoi singleInstance ne fonctionne pas. Si quelqu'un sait s'il vous plaît fournir plus d'informations.
Ma solution consistait donc à changer launchMode et à utiliser les éléments déjà possédés. Depuis ce temps, le PAI fonctionne bien pour moi.