React-native-iap: Android se bloquea en muchos dispositivos después del lanzamiento

Creado en 9 nov. 2018  ·  45Comentarios  ·  Fuente: dooboolab/react-native-iap

Versión de react-native-iap

"react-native": "0.55.4"
"react-native-iap": "^ 2.3.2"

Plataformas a las que se enfrentó el error (¿IOS o Android o ambos?)

Androide

Comportamiento esperado

Por favor, ayúdame, necesito solucionar este problema de inmediato. Porque ya hay + 2k usuarios

Comportamiento real

La aplicación se bloquea debido a rniap en muchos dispositivos. En la consola de juegos, vi que este error provoca el bloqueo:
java.lang.RuntimeException:

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

Entorno probado (¿Emulador? ¿Dispositivo real?)

aquí está el informe de la consola de juego:
https://ibb.co/gDxZQA

Pasos para reproducir el comportamiento

No sé qué hacer, usé rniap como en el ejemplo.
en componentDidMount:
tratar {
resultado constante = espera RNIap.initConnection ();
} atrapar (err) {
console.log (err);
}
en componentWillUnmount:
RNIap.endConnection ();

🐛 bug 🤖 android

Comentario más útil

@hyochan lo siento, no

@ Ilario17 Probablemente sea para señalar que hay un error lógico en alguna parte, para ser justos, no deberíamos llamar a ese método varias veces

edit: ah, el problema surge cuando onBillingSetupFinished ocurre más de una vez. En el ensureConnection necesitamos eliminar el oyente cuando hayamos terminado (es decir, cuando llamamos a callback.run() o rechazamos la promesa pasada). ¡Debería ser un PR fácil si alguien quiere algo de karma gratis! De lo contrario, intentaré llegar pronto

Todos 45 comentarios

¿Podrías probar nuestra versión reciente 2.3.19 y regresar?

No puedo. Porque fue una situación inmediata. Entonces, cambié el paquete iap. Ahora no hay fallos en + 3000 usuarios. Pero gracias. Lo intentaré en mi próximo proyecto.

Hola, ¿puedes reabrir este problema? Tengo el mismo problema y estoy usando la versión 2.3.21

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

este es mi 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 ¿Podrías ayudarnos aquí? ¿Por qué callback.run() bloquea en el lanzamiento? ¿Deberíamos comprobar si callback es nulo en ensureConnection ? Hm. es un runtime exception .

Hmmm, ¿qué significa RuntimeException aquí? ¿No hay más información? @hyochan, ¿por qué crees que callback era null ? 🤔

@LinusU Gracias por sus comentarios. Actualmente no tengo ni idea. Acabo de ver la línea del problema a continuación.
image

En RNIapModule.java línea 124,

callback.run();

¿Tienes alguna idea más?

@LinusU Si no tiene idea de esto, consideraría revertirlo a donde estábamos anteriormente.

Bien, aquí está el problema:

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

Por alguna razón, llamamos a la devolución de llamada más de una vez, ¡debería ser fácil de solucionar!

@LinusU ¡Se ve genial porque estás en una pista! ¿Podrías darnos un PR por esto?

¿Por qué hay una RuntimeException en ese método?

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

¿No es suficiente algo como esto?

@hyochan lo siento, no

@ Ilario17 Probablemente sea para señalar que hay un error lógico en alguna parte, para ser justos, no deberíamos llamar a ese método varias veces

edit: ah, el problema surge cuando onBillingSetupFinished ocurre más de una vez. En el ensureConnection necesitamos eliminar el oyente cuando hayamos terminado (es decir, cuando llamamos a callback.run() o rechazamos la promesa pasada). ¡Debería ser un PR fácil si alguien quiere algo de karma gratis! De lo contrario, intentaré llegar pronto

@LinusU Entonces, ¿te refieres a onBillingSetupFinished , deberíamos eliminar el billingClientStateListener ? ¿Alguien probaría este para ser parte de nosotros?

Si desea una solución rápida y sucia, agregaría una variable local a esa función, didCallCallback = false . Luego guarde la llamada a callback.run() detrás de if (didCallCallback) { didCallCallback = true; callback.run() } .

Una solución más limpia sería simplemente cancelar el registro del oyente después de la primera llamada por completo ...

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

Acabo de lanzar 2.4.0-beta2 para corregir esto. Por favor, inténtalo.

@hyochan probaré esta nueva versión

Intente 2.4.0-beta3 ya que beta2 tuvo problemas de regresión.

@hyochan después de la actualización, el error sigue ahí :(

@ Ilario17 ¿Qué hay de 2.4.0-beta5 ? Como no puedo reproducir esto en mi lado, necesito tu prueba :(

@hyochan, ¿ @LinusU ?

@ Ilario17 Tenía curiosidad por saber si esa es la solución correcta. Además, creo que onBillingServiceDisconnected deberían ser notificados. Puede intentar quitarlo y probarlo en su costado y ver si funciona.

No sé si esto está relacionado, pero tengo este bloqueo en 2.4.0-beta5. Es fácil de reproducir en el emulador:
Monto el componente donde se carga IAP, lo desmonto y luego lo vuelvo a montar, boom crash.
EDITAR: Bajé a esta confirmación y ya no se bloquea 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

Aquí está el código que causa el bloqueo en el segundo montaje (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 Bueno, esto no funcionaría en el emulador de Android. Inténtelo en un dispositivo real.

@hyochan Noto que la versión 2.4.0-beta3 tiene un 50% menos de fallas, pero aún no es suficiente

Para 2.4.0-beta3 en Android, aparece el error "Error en la compra con el código: 0 (OK)" solo por llamar a getProducts. beta 4 y 5 en realidad hacen que falle. Bajé a 2.3.5 y funciona bien, pero necesito las correcciones de errores del oyente de ios en 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)
    }
};

¿Podrías probar beta5 y comeback? Hubo un error en esa versión, así que arreglé rápidamente

@hyochan @LinusU con la versión 2.4.0-beta5 el error sigue ahí.

Tengo información relevante para esta discusión.

En 2.4.0-beta5, recibo el siguiente error

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

apuntando a RNIapModule.java línea 223. Esto implica que mBillingClient es inesperadamente null aquí.

Para reproducir : monte un componente react-native que llame a RNIap.getProducts() en componentDidMount y RNIap.endConnection() en componentWillUnmount . Desmonte el componente y vuelva a montarlo. Debería producirse el error anterior.

La variable clientReady se usa para rastrear si se ha completado la configuración del cliente de facturación, configurándola en false en la devolución onBillingServiceDisconnected() llamada mBillingClient sí mismo se establece en nulo inmediatamente cuando se llama a endConnection() . Este es un desajuste. Es posible que clientReady permanezca establecido en true , incluso si mBillingClient es nulo. Creo que esto es lo que está pasando, al menos por mi error. Parece que algo impide que se llame a onBillingServiceDisconnected() .

Puedo confirmar que no obtengo "billing client disconnected" en logcat en unmount como se esperaba, por lo que onBillingServiceDisconnected() hecho no se está llamando.

Corrección potencial : establezca clientReady = false dentro del método endConnection() (por ejemplo, después de la línea 179). Probé esto en el dispositivo y parece funcionar. Volver a montar el componente de compra en la aplicación varias veces no parece dar como resultado ningún error o bloqueo. Además, piense si es necesario establecer mBillingClient en nulo. No tengo ninguna experiencia aquí, así que no puedo decirlo, pero parece un poco extraño. Tampoco veo ningún otro proyecto en Github que anule el cliente de facturación en esta devolución de llamada.

@ mitchellmcm27 Gracias por tu captura. Esto es muy prometedor y estoy de acuerdo contigo. Fue difícil para mí solucionar el problema sin una reproducción mínima. Además, me gustaría resolver los problemas juntos.

Por favor dénos cualquier PR si tiene alguna idea de mejorar este problema.

Atentamente.

Lancé 2.4.0-beta6 en la última versión de mi aplicación, con algunos miles de actualizaciones hasta ahora. No hay bloqueos todavía 👍

Suena genial. ¡Muchas gracias por la solución! Cerraré este tema por ahora.

Ya tengo algunos fallos con el mismo stacktrace pero mucho menos que antes.


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)

También sigue obteniendo el mismo stacktrace en 2.4.0-beta6

Creo que este error debería reabrirse.

schermata 2019-01-11 alle 10 51 20

120 choques en menos de 24 horas.

No estoy seguro de que los cambios recientes no hayan causado sus propios problemas, por ejemplo, si mBillingClient no es nulo, pero aún no está listo, la función ensureConnection simplemente sobrescribirá mBillingClient con un nuevo cliente, desechando el anterior 🤔

Me gustaría saber qué versión comenzó a mostrar este error, para poder volver a una versión estable.

Yo también creo que el tema debería reabrirse. El problema original tenía que ver con la devolución de llamada, y las soluciones para eso surgieron el error de "referencia de objeto nulo". Aunque es posible que se haya solucionado este último (estoy de acuerdo con @LinusU en que puede haber más problemas allí), todavía estamos lidiando con el problema original.

También he tenido algunos fallos relacionados con la devolución de llamada en beta6.

He vuelto a abrir esto. Espero que alguien pueda dar PR por esto.

¿Saben cuando se introdujo esto? Estaría más que feliz de retroceder.

Puedo confirmar que existen fallos en beta6 y 2.3.23 en Android. Bastante fácil de recrear según este [1] comentario.

Editar: Ahora que estoy en casa, estoy depurando el código nativo de Android para beta6. En caso de que esto sea útil, esto es lo que está sucediendo (al menos en mi aplicación, llamando a getAvailablePurchases):

  1. getAvailableItemsByType para "inapp" se llama sin la configuración de mBillingClient todavía.
  2. El cliente de facturación se configura, se llama a onBillingSetupFinished en el oyente y se consume (resuelve) la devolución de llamada (Promise). El oyente todavía existe.
  3. getAvailableItemsByType para "subs" se llama con la configuración de mBillingClient. la nueva devolución de llamada (Promesa) se consume (resuelve).
  4. Elimine el servicio Play Store: se llama onServiceDisconnected en BillingClientImpl, el oyente de la parte 1 lo maneja. Se inicia un nuevo servicio y el oyente de la parte 1 maneja el onBillingSetupFinished e intenta consumir la devolución de llamada (Promise) del paso uno y se vuelve a llamar.

Experimentaré matando al oyente una vez que ya no sea necesario.

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

He fusionado # 379 y lanzado a beta8 . Por favor intente eso.

¿Está arreglado en la última versión? ¿Es seguro actualizar a la última?

@hyochan este problema todavía aparece en 3.0.0-rc-2 ¿alguna idea?

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 ¿Podrías probar 3.0.0-rc-4 ? Funcionará perfectamente (con suerte).

@hyochan Si uso try catch este error de tiempo de ejecución no ocurrirá, creo que rc-4 debería resolverlo.
Gracias !

¿Fue útil esta página
0 / 5 - 0 calificaciones