React-native-iap: Android plante sur de nombreux appareils après sa sortie

Créé le 9 nov. 2018  ·  45Commentaires  ·  Source: dooboolab/react-native-iap

Version de react-native-iap

"natif réactif": "0,55,4"
"react-native-iap": "^ 2.3.2"

Plateformes sur lesquelles vous avez rencontré l'erreur (IOS ou Android ou les deux?)

Android

Comportement attendu

S'il vous plaît, aidez-moi, je dois résoudre ce problème immédiatement. Parce qu'il y a déjà + 2k utilisateurs

Comportement réel

L'application se bloque en raison de rniap sur de nombreux appareils. Dans la console de jeu, j'ai vu que cette erreur provoquait le crash:
java.lang.RuntimeException:

  1. à com.facebook.react.bridge.CallbackImpl.invoke (CallbackImpl.java:28)
  2. à com.facebook.react.bridge.PromiseImpl.resolve (PromiseImpl.java:30)
  3. à com.dooboolab.RNIap.RNIapModule $ 4.run (RNIapModule.java:154)
  4. à com.dooboolab.RNIap.RNIapModule $ 3.onBillingSetupFinished (RNIapModule.java:123)
  5. à com.android.billingclient.api.BillingClientImpl $ BillingServiceConnection.onServiceConnected (BillingClientImpl.java:903)
  6. à android.app.LoadedApk $ ServiceDispatcher.doConnected (LoadedApk.java:1264)
  7. à android.app.LoadedApk $ ServiceDispatcher $ RunConnection.run (LoadedApk.java:1281)
  8. à android.os.Handler.handleCallback (Handler.java:815)
  9. à android.os.Handler.dispatchMessage (Handler.java:104)
  10. à android.os.Looper.loop (Looper.java:207)
  11. à android.app.ActivityThread.main (ActivityThread.java:5692)
  12. à java.lang.reflect.Method.invoke (méthode native)
  13. à com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:908)
  14. à com.android.internal.os.ZygoteInit.main (ZygoteInit.java:769)

Environnement testé (émulateur? Real Device?)

voici le rapport de la console de jeu:
https://ibb.co/gDxZQA

Étapes pour reproduire le comportement

Je ne sais pas quoi faire, j'ai utilisé rniap comme dans l'exemple.
dans componentDidMount:
essayez {
résultat const = attendre RNIap.initConnection ();
} catch (err) {
console.log (err);
}
dans componentWillUnmount:
RNIap.endConnection ();

🐛 bug 🤖 android

Commentaire le plus utile

@hyochan désolé,

@ Ilario17 C'est probablement pour

edit: ah, le problème survient lorsque onBillingSetupFinished se produit plus d'une fois. Dans le ensureConnection nous devons supprimer l'auditeur lorsque nous avons terminé (c'est-à-dire lorsque nous appelons callback.run() ou rejetons la promesse passée). Cela devrait être un PR facile si quelqu'un veut du karma gratuit! Sinon j'essaierai d'y arriver bientôt

Tous les 45 commentaires

Pourriez-vous essayer notre version récente 2.3.19 et revenir?

Je ne peux pas. Parce que c'était une situation immédiate. Donc, j'ai changé le package iap. Il n'y a plus de plantages chez + 3k utilisateurs. Mais merci. Je vais l'essayer dans mon prochain projet.

Bonjour, pouvez-vous rouvrir ce numéro? J'ai le même problème et j'utilise la version 2.3.21

java.lang.RuntimeException:
à com.facebook.react.bridge.CallbackImpl.invoke (CallbackImpl.java:28)
à com.facebook.react.bridge.PromiseImpl.resolve (PromiseImpl.java:30)
à com.dooboolab.RNIap.RNIapModule $ 4.run (RNIapModule.java:155)
à com.dooboolab.RNIap.RNIapModule $ 3.onBillingSetupFinished (RNIapModule.java:124)
à com.android.billingclient.api.BillingClientImpl $ BillingServiceConnection.onServiceConnected (BillingClientImpl.java:903)
à android.app.LoadedApk $ ServiceDispatcher.doConnected (LoadedApk.java:1658)
à android.app.LoadedApk $ ServiceDispatcher $ RunConnection.run (LoadedApk.java:1687)
à android.os.Handler.handleCallback (Handler.java:789)
à android.os.Handler.dispatchMessage (Handler.java:98)
à android.os.Looper.loop (Looper.java:164)
à android.app.ActivityThread.main (ActivityThread.java:6938)
à java.lang.reflect.Method.invoke (méthode native)
à com.android.internal.os.Zygote $ MethodAndArgsCaller.run (Zygote.java:327)
à com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)

c'est mon componentDidMount

           const itemSKus = Platform.select({
            ios: [
                ...
            ],
            android: [
                ...
            ]
        });

        try {
            const message = await RNIap.initConnection();
            //console.log(`message = ${message}`);
            const items = await RNIap.getProducts(itemSKus);
            //console.log(`items = ${items.length}`);
            //console.log(items);
            this.props.storeInAppPurchaseList(items);
        } catch (errorCode) {
            console.log(`error rniap = ${errorCode}`);
        }

@LinusU Pourriez-vous nous aider ici? Pourquoi callback.run() plante-t-il dans la version? Doit-on vérifier si callback est nul dans ensureConnection ? Hm. c'est un runtime exception .

Hmmm, que signifie RuntimeException ici, n'y a-t-il plus d'informations? @hyochan pourquoi pensez-vous que callback était null ? 🤔

@LinusU Merci pour vos commentaires. Je n'en ai aucune idée actuellement. Je viens de voir la ligne de problème ci-dessous.
image

Dans RNIapModule.java ligne 124,

callback.run();

Avez-vous une autre idée?

@LinusU Si vous n'avez aucune idée de celui-ci,

Bon, voici le problème:

https://github.com/facebook/react-native/blob/370bcffba748e895ad8afa825bfef40bff859c95/ReactAndroid/src/main/java/com/facebook/react/bridge/CallbackImpl.java#L27 -L31

Pour une raison quelconque, nous appelons le rappel plus d'une fois, cela devrait être facile à réparer!

@LinusU a l'air génial parce que vous êtes dans une piste! Pouvez-vous nous donner un PR pour cela?

Pourquoi y a-t-il une RuntimeException dans cette méthode?

if (!mInvoked) {
   mJSInstance.invokeCallback(mCallbackId, Arguments.fromJavaArgs(args));
   mInvoked = true;
}

quelque chose comme ça ne suffit pas?

@hyochan désolé,

@ Ilario17 C'est probablement pour

edit: ah, le problème survient lorsque onBillingSetupFinished se produit plus d'une fois. Dans le ensureConnection nous devons supprimer l'auditeur lorsque nous avons terminé (c'est-à-dire lorsque nous appelons callback.run() ou rejetons la promesse passée). Cela devrait être un PR facile si quelqu'un veut du karma gratuit! Sinon j'essaierai d'y arriver bientôt

@LinusU Alors voulez-vous dire onBillingSetupFinished , nous devrions supprimer le billingClientStateListener ? Quelqu'un essayerait-il celui-ci pour faire partie de nous?

Si vous voulez une solution rapide et sale, j'ajouterais une variable locale à cette fonction, didCallCallback = false . Ensuite, gardez l'appel à callback.run() derrière if (didCallCallback) { didCallCallback = true; callback.run() } .

Une solution plus propre serait simplement de désenregistrer complètement l'auditeur après le premier appel ...

Log.d(TAG, "billing client ready");
callback.run();
//deregister the listener here?

Je viens de publier 2.4.0-beta2 pour corriger ce problème. S'il vous plaît essayez.

@hyochan je vais essayer cette nouvelle version

Veuillez essayer la version 2.4.0-beta3 car la beta2 a eu un problème de régression.

@hyochan après la mise à jour, l'erreur est toujours là :(

@ Ilario17 Et pour 2.4.0-beta5 ? Puisque je ne peux pas reproduire cela de mon côté, j'ai besoin de votre test :(

@hyochan pourquoi ne pas simplement supprimer l'auditeur, comme l' a dit

@ Ilario17 J'étais curieux de savoir si c'était la bonne solution. De plus, je pense que onBillingServiceDisconnected devrait être notifié. Vous pouvez essayer de le supprimer et tester cela de votre côté et voir si cela fonctionne.

Je ne sais pas si cela est lié mais j'obtiens ce crash dans la version 2.4.0-beta5. Il est facile de reproduire dans l'émulateur:
Je monte le composant là où IAP se charge, le démonte puis le monte à nouveau, crash de la flèche.
EDIT: J'ai rétrogradé à ce commit et il ne plante plus https://github.com/dooboolab/react-native-iap/commit/2db337ac770a93508507ec046f31085ddbb346fb

Attempt to invoke virtual method 'void com.android.billingclient.api.BillingClient.querySkuDetailsAsync(com.android.billingclient.api.SkuDetailsParams, com.android.billingclient.api.SkuDetailsResponseListener)' on a null object reference
run
    RNIapModule.java:223
ensureConnection
    RNIapModule.java:113
getItemsByType
    RNIapModule.java:218
invoke
    Method.java
invoke
    JavaMethodWrapper.java:372
invoke
    JavaModuleWrapper.java:160
run
    NativeRunnable.java
handleCallback
    Handler.java:789
dispatchMessage
    Handler.java:98
dispatchMessage
    MessageQueueThreadHandler.java:29
loop
    Looper.java:164
run
    MessageQueueThreadImpl.java:192
run
    Thread.java:764

Voici le code qui provoque le crash sur le 2ème montage (2.4.0-beta5):

componentDidMount() {
    this.loadIAPProducts()
}

componentWillUnmount() {
    RNIap.endConnection();
}

loadIAPProducts = async () => {
    const itemSkus = ['XXXX_id']

    const result = await RNIap.initConnection();
    if(result) {
      try {
        const products = await RNIap.getProducts(itemSkus);
        if (products) {
          this.setState({ iapProducts: products })
        }
      } catch (err) {
        //console.log(err); // standardized err.code and err.message available
      }

      this.restoreIAPPurchases()
    }
  }

  restoreIAPPurchases = async () => {
    try {
      const purchases = await RNIap.getAvailablePurchases()
      if(purchases) {
        purchases.forEach(purchase => {
          if (purchase.productId === 'XXXX_id') {
            try {
              RNIap.consumePurchase(purchase.purchaseToken);
            } catch(err) {

            }
          }
        })
      }
    } catch (err) {
      //console.log(err)
    }
  }

@ rom1k Eh bien, cela ne fonctionnerait pas dans l'émulateur Android. Veuillez essayer sur un appareil réel.

@hyochan je remarque que la version 2.4.0-beta3 a un crash de 50% moins, mais toujours pas assez

Pour 2.4.0-beta3 sur Android, j'obtiens l'erreur "Achat échoué avec le code: 0 (OK)" juste en appelant getProducts. bêta 4 et 5 le font planter. J'ai rétrogradé à la version 2.3.5 et cela fonctionne bien, mais j'ai besoin des corrections de bogues de l'écouteur ios dans la version 2.4.0-beta

''
componentDidMount () {
this.getProductDetails ();
}

getProductDetails = async () => {
    try {
        await RNIap.initConnection();
        const details = await RNIap.getProducts(products);
        this.setState({
            title: details[0].title,
            description: details[0].description,
            price: details[0].localizedPrice,
            loading: false
        });
    } catch (err) {
        console.log(err.message)
    }
};

Pourriez-vous essayer beta5 et revenir? Il y avait une erreur dans cette version alors j'ai rapidement corrigé

@hyochan @LinusU avec la version 2.4.0-beta5 l'erreur est toujours là.

J'ai quelques informations pertinentes pour cette discussion.

Sur 2.4.0-beta5, j'obtiens l'erreur suivante

Attempt to invoke virtual method void com.android.billingclient.api.BillingClient.querySkuDetailsAsync(...) on a null object reference

pointant vers RNIapModule.java ligne 223. Cela implique que mBillingClient est inopinément null ici.

Pour reproduire : montez un composant natif de réaction qui appelle RNIap.getProducts() sur componentDidMount et RNIap.endConnection() sur componentWillUnmount . Démontez le composant et remontez-le. L'erreur ci-dessus devrait se produire.

La variable clientReady est utilisée pour suivre si la configuration du client de facturation est terminée, en la définissant sur false dans le rappel onBillingServiceDisconnected() . Mais mBillingClient lui-même est mis à null immédiatement lorsque endConnection() est appelé. C'est un décalage. Il est possible que clientReady reste défini sur true , même si mBillingClient est nul. Je crois que c'est ce qui se passe, du moins pour mon erreur. Il semble que quelque chose empêche onBillingServiceDisconnected() d'être appelé.

Je peux confirmer que je ne reçois pas "billing client disconnected" dans logcat lors du démontage comme prévu, donc onBillingServiceDisconnected() n'est effectivement pas appelé.

Correction potentielle : définissez clientReady = false dans la méthode endConnection() (par exemple après la ligne 179). J'ai testé cela sur l'appareil et cela semble fonctionner. Remonter plusieurs fois le composant d'achat intégré à l'application ne semble pas entraîner d'erreurs ou de plantages. Pensez également à savoir s'il est nécessaire de définir mBillingClient sur null? Je n'ai aucune expérience ici, donc je ne peux pas le dire, mais cela semble un peu étrange. Je ne vois pas non plus d'autres projets sur Github annulant le client de facturation dans ce rappel.

@ mitchellmcm27 Merci pour votre prise. C'est très prometteur et je suis d'accord avec vous. Il était difficile pour moi de résoudre le problème sans aucune reproduction minimale. Aussi, j'aimerais résoudre les problèmes ensemble.

Veuillez nous donner un PR si vous avez des idées pour améliorer ce problème.

Meilleures salutations.

J'ai publié 2.4.0-beta6 dans la dernière version de mon application, avec quelques milliers de mises à niveau jusqu'à présent. Pas encore de plantages 👍

Super. Merci beaucoup pour le correctif! Je vais clôturer ce numéro pour le moment.

J'ai déjà des plantages avec le même stacktrace mais beaucoup moins qu'avant.


java.lang.RuntimeException: 
  at com.facebook.react.bridge.CallbackImpl.invoke (CallbackImpl.java:28)
  at com.facebook.react.bridge.PromiseImpl.resolve (PromiseImpl.java:30)
  at com.dooboolab.RNIap.RNIapModule$4.run (RNIapModule.java:155)
  at com.dooboolab.RNIap.RNIapModule$3.onBillingSetupFinished (RNIapModule.java:124)
  at com.android.billingclient.api.BillingClientImpl$BillingServiceConnection.onServiceConnected (BillingClientImpl.java:903)
  at android.app.LoadedApk$ServiceDispatcher.doConnected (LoadedApk.java:1658)
  at android.app.LoadedApk$ServiceDispatcher$RunConnection.run (LoadedApk.java:1687)
  at android.os.Handler.handleCallback (Handler.java:789)
  at android.os.Handler.dispatchMessage (Handler.java:98)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6944)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:327)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)

Toujours obtenir le même stacktrace sur 2.4.0-beta6

Je pense que ce bug devrait être rouvert.

schermata 2019-01-11 alle 10 51 20

120 crash en moins de 24 heures.

Je ne suis pas sûr que les changements récents n'aient pas causé leurs propres problèmes, par exemple si mBillingClient n'est pas nul, mais qu'il n'est pas encore prêt, la fonction ensureConnection écrasera simplement mBillingClient avec un nouveau client, jetant l'ancien 🤔

Je voudrais savoir quelle version a commencé à afficher cette erreur, afin que je puisse revenir à une version stable.

Je pense moi aussi que la question devrait être rouverte. Le problème d'origine avait à voir avec le rappel, et les correctifs pour cela ont fait surface l'erreur "référence d'objet nul". Bien que ce dernier puisse avoir été corrigé (je suis d'accord avec @LinusU qu'il peut y avoir plus de problèmes là-bas), nous sommes toujours aux prises avec le problème d'origine.

J'ai également eu quelques plantages liés au rappel de la version beta6.

J'ai rouvert ceci. J'espère que quelqu'un pourra donner PR pour ça.

Savez-vous quand cela a été introduit? Je serais plus qu'heureux de revenir en arrière.

Je peux confirmer que les plantages existent sur beta6 ainsi que 2.3.23 sur Android. Assez facile à recréer par ce [1] commentaire.

Edit: Maintenant que je suis à la maison, je débogue dans le code natif Android pour beta6. Au cas où cela serait utile, voici ce qui se passe (au moins dans mon application, en appelant getAvailablePurchases):

  1. getAvailableItemsByType pour "inapp" est appelé sans la configuration de mBillingClient pour le moment.
  2. Le client de facturation est configuré, le onBillingSetupFinished dans l'écouteur est appelé et le rappel (Promise) est consommé (résolu). L'auditeur existe toujours.
  3. getAvailableItemsByType pour "subs" est appelé avec la configuration de mBillingClient. le nouveau rappel (Promise) est consommé (résolu).
  4. Tuez le service Play Store - onServiceDisconnected dans BillingClientImpl est appelé, l'auditeur de la partie 1 le gère. Un nouveau service démarre et l'écouteur de la partie 1 gère le onBillingSetupFinished et essaie de consommer le rappel (Promise) de la première étape est appelé à nouveau.

J'essaierai de tuer l'auditeur une fois que ce n'est plus nécessaire.

[1]
https://github.com/googlesamples/android-play-billing/issues/45#issuecomment -324466519

J'ai fusionné # 379 et publié dans beta8 . Veuillez essayer ça.

Est-ce corrigé dans la dernière version? Est-il sûr de passer à la dernière version?

@hyochan ce problème apparaît toujours dans 3.0.0-rc-2 une idée?

java.lang.RuntimeException
com.dooboolab.RNIap.RNIapModule$3.onBillingSetupFinished

java.lang.RuntimeException: 
  at com.facebook.react.bridge.CallbackImpl.invoke (CallbackImpl.java:28)
  at com.facebook.react.bridge.PromiseImpl.resolve (PromiseImpl.java:30)
  at com.dooboolab.RNIap.RNIapModule$3.onBillingSetupFinished (RNIapModule.java:129)
  at com.android.billingclient.api.BillingClientImpl$BillingServiceConnection$1.run (BillingClientImpl.java:1518)
  at android.os.Handler.handleCallback (Handler.java:739)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:148)
  at android.app.ActivityThread.main (ActivityThread.java:7325)
  at java.lang.reflect.Method.invoke (Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)

@fokoz Pourriez-vous essayer 3.0.0-rc-4 ? Cela fonctionnera parfaitement (espérons-le).

@hyochan Si j'utilise try catch cette erreur d'exécution ne se produira pas, je pense que rc-4 devrait résoudre ce problème.
Merci !

Cette page vous a été utile?
0 / 5 - 0 notes