React-native-iap: O Android trava em muitos dispositivos após o lançamento

Criado em 9 nov. 2018  ·  45Comentários  ·  Fonte: dooboolab/react-native-iap

Versão do react-native-iap

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

Plataformas em que você enfrentou o erro (IOS ou Android ou ambos?)

Android

Comportamento esperado

Por favor me ajude, eu preciso consertar isso imediatamente. Porque já existem + 2 mil usuários

Comportamento real

O aplicativo trava devido ao rniap em muitos dispositivos. No Play Console, vi que este erro causa a falha:
java.lang.RuntimeException:

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

Ambiente testado (emulador? Dispositivo real?)

aqui está o relatório do console de jogo:
https://ibb.co/gDxZQA

Passos para reproduzir o comportamento

Não sei o que fazer, usei rniap como no exemplo.
em componentDidMount:
tentar {
resultado const = espera RNIap.initConnection ();
} catch (errar) {
console.log (errar);
}
em componentWillUnmount:
RNIap.endConnection ();

🐛 bug 🤖 android

Comentários muito úteis

@hyochan desculpe, não tive tempo para olhar para isso ontem, espero poder dar uma olhada em breve

@ Ilario17 É provavelmente para sinalizar que há um erro lógico em algum lugar, para ser justo, não devemos chamar esse método várias vezes

editar: ah, o problema surge quando onBillingSetupFinished acontece mais de uma vez. No ensureConnection , precisamos remover o ouvinte quando terminarmos (ou seja, quando chamarmos callback.run() ou rejeitarmos a promessa passada). Deve ser um RP fácil se alguém quiser carma grátis! Caso contrário, vou tentar fazer isso em breve

Todos 45 comentários

Você poderia tentar nossa versão recente 2.3.19 e voltar?

Eu não posso. Porque foi uma situação imediata. Então, mudei o pacote iap. Agora não há travamentos em +3 mil usuários. Mas, obrigado. Vou tentar no meu próximo projeto.

Olá, você pode reabrir este problema? Estou com o mesmo problema e estou usando a versão 2.3.21

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

este é meu componenteDidMount

           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 Você poderia nos ajudar aqui? Por que callback.run() travaria no lançamento? Devemos verificar se callback é nulo em ensureConnection ? Hm. é um runtime exception .

Hmmm, o que RuntimeException significa aqui, não há mais informações? @hyochan por que você acha que callback era null ? 🤔

@LinusU Obrigado pelo seu feedback. Não tenho ideia atualmente. Acabei de ver a linha de problema abaixo.
image

Na linha RNIapModule.java 124,

callback.run();

Você tem alguma ideia adicional?

@LinusU Se você não tem nenhuma ideia sobre este, eu consideraria voltar para onde estávamos antes.

Ok, aqui está o problema:

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

Por alguma razão, estamos chamando o retorno de chamada mais de uma vez, deve ser fácil de corrigir!

@LinusU Parece ótimo porque você está em uma pista! Você poderia nos dar um PR por isso?

Por que existe um RuntimeException nesse método?

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

não é algo assim o suficiente?

@hyochan desculpe, não tive tempo para olhar para isso ontem, espero poder dar uma olhada em breve

@ Ilario17 É provavelmente para sinalizar que há um erro lógico em algum lugar, para ser justo, não devemos chamar esse método várias vezes

editar: ah, o problema surge quando onBillingSetupFinished acontece mais de uma vez. No ensureConnection , precisamos remover o ouvinte quando terminarmos (ou seja, quando chamarmos callback.run() ou rejeitarmos a promessa passada). Deve ser um RP fácil se alguém quiser carma grátis! Caso contrário, vou tentar fazer isso em breve

@LinusU Então você quer dizer onBillingSetupFinished , devemos remover billingClientStateListener ? Alguém experimentaria este para fazer parte de nós?

Se você quiser uma solução rápida e suja, eu adicionaria uma variável local a essa função, didCallCallback = false . Em seguida, guarde a chamada para callback.run() atrás de if (didCallCallback) { didCallCallback = true; callback.run() } .

Uma solução mais limpa seria simplesmente cancelar o registro do ouvinte completamente após a primeira chamada ...

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

Acabei de lançar 2.4.0-beta2 para corrigir isso. Tente por favor.

@hyochan vou tentar esta nova versão

Tente 2.4.0-beta3, pois o beta2 teve problemas de regressão.

@hyochan após a atualização, o erro ainda está lá :(

@ Ilario17 E quanto a 2.4.0-beta5 ? Como não consigo reproduzir isso do meu lado, preciso do seu teste :(

@hyochan porque não apenas remover o ouvinte, como disse @LinusU ?

@ Ilario17 Fiquei curioso para onBillingServiceDisconnected deve ser notificado. Você pode tentar removê-lo e testar isso do seu lado para ver se funciona.

Não sei se isso está relacionado, mas estou recebendo essa falha no 2.4.0-beta5. É fácil de reproduzir no emulador:
Eu monto o componente onde o IAP é carregado, desmonto e monte novamente, boom crash.
EDIT: Eu fiz downgrade para este commit e ele não trava mais 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

Este é o código que causa a falha na segunda montagem (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 Bem, isso não funcionaria no emulador de Android. Por favor, tente em um dispositivo real.

@hyochan percebi que a versão 2.4.0-beta3 tem um travamento 50% menor, mas ainda não o suficiente

Para 2.4.0-beta3 no Android, estou recebendo o erro "Falha na compra com o código: 0 (OK)" apenas ao chamar getProducts. beta 4 e 5 realmente causam o travamento. Fiz downgrade para 2.3.5 e funciona bem, mas preciso das correções de bug do ouvinte ios no 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)
    }
};

Você poderia tentar o beta5 e voltar? Havia um erro nessa versão, então eu rapidamente corrigi

@hyochan @LinusU com a versão 2.4.0-beta5 o erro ainda está lá.

Eu tenho algumas informações relevantes para esta discussão.

Em 2.4.0-beta5, estou recebendo o seguinte erro

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

apontando para RNIapModule.java linha 223. Isso implica que mBillingClient está inesperadamente null aqui.

Para reproduzir : monte um componente reativo nativo que chama RNIap.getProducts() em componentDidMount e RNIap.endConnection() em componentWillUnmount . Desmonte o componente e monte-o novamente. O erro acima deve ocorrer.

A variável clientReady está sendo usada para rastrear se a configuração do cliente de faturamento foi concluída, definindo-a false no retorno de chamada onBillingServiceDisconnected() . Mas mBillingClient si é definido como nulo imediatamente quando endConnection() é chamado. Isso é uma incompatibilidade. É possível que clientReady permaneça definido como true , mesmo se mBillingClient for nulo. Acredito que é isso que está acontecendo, pelo menos por erro meu. Parece que algo está impedindo onBillingServiceDisconnected() de ser chamado.

Posso confirmar que não estou recebendo "billing client disconnected" no logcat ao desmontar conforme o esperado, então onBillingServiceDisconnected() realmente não está sendo chamado.

Solução potencial : defina clientReady = false dentro do método endConnection() (por exemplo, após a linha 179). Eu testei isso no dispositivo e parece funcionar. Remontar o componente de compra no aplicativo várias vezes não parece resultar em erros ou travamentos. Além disso, pense se é necessário definir mBillingClient como nulo? Não tenho nenhuma experiência aqui, então não posso dizer, mas parece um pouco estranho. Eu também não vejo nenhum outro projeto no Github anulando o cliente de cobrança neste retorno de chamada.

@ mitchellmcm27 Obrigado por sua pegada. Isso é muito promissor e concordo com você. Foi difícil para mim resolver o problema sem qualquer reprodução mínima. Além disso, gostaria de resolver os problemas juntos.

Forneça-nos PR se tiver alguma ideia de melhorar este problema.

Atenciosamente.

Eu lancei 2.4.0-beta6 na versão mais recente do meu aplicativo, com alguns milhares de atualizações até agora. Nenhuma falha ainda 👍

Parece bom. Muito obrigado pela correção! Vou encerrar esse problema por enquanto.

Já tenho algum travamento com o mesmo rastreamento de pilha, mas muito menos do 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)

Também ainda obtendo o mesmo rastreamento de pilha em 2.4.0-beta6

Acho que esse bug deve ser reaberto.

schermata 2019-01-11 alle 10 51 20

120 batem em menos de 24 horas.

Não tenho certeza se as mudanças recentes não causaram seus próprios problemas, por exemplo, se mBillingClient não for nulo, mas ainda não estiver pronto, a função ensureConnection simplesmente substituirá mBillingClient com um novo cliente, jogando fora o antigo 🤔

Gostaria de saber qual versão começou a mostrar esse erro, para que eu possa reverter para uma versão estável.

Eu também acho que a questão deveria ser reaberta. O problema original tinha a ver com o retorno de chamada e as correções para isso trouxeram à tona o erro de "referência de objeto nulo". Embora o último possa ter sido corrigido (concordo com @LinusU que pode haver mais problemas lá), ainda estamos lidando com o problema original.

Também recebi alguns travamentos relacionados ao retorno de chamada no beta6.

Eu reabri isso. Espero que alguém possa dar PR por isso.

Vocês sabem quando isso foi introduzido? Eu ficaria mais do que feliz em voltar.

Posso confirmar que as falhas existem no beta6, bem como no 2.3.23 no Android. Bastante fácil de recriar de acordo com este [1] comentário.

Edit: Agora que estou em casa, estou depurando no código nativo do Android para beta6. Caso isso seja útil, é o que está acontecendo (pelo menos em meu aplicativo, chamando getAvailablePurchases):

  1. getAvailableItemsByType para "inapp" é chamado ainda sem a configuração de mBillingClient.
  2. O cliente de faturamento é configurado, o onBillingSetupFinished no ouvinte é chamado e o retorno de chamada (Promessa) é consumido (resolvido). O ouvinte ainda existe.
  3. getAvailableItemsByType para "subs" é chamado com a configuração de mBillingClient. o novo retorno de chamada (Promise) é consumido (resolvido).
  4. Elimine o serviço da Play Store - onServiceDisconnected em BillingClientImpl é chamado, o ouvinte da parte 1 cuida disso. Um novo serviço é iniciado e o ouvinte da parte 1 lida com onBillingSetupFinished e tenta consumir o retorno de chamada (Promise) da etapa um é chamado novamente.

Vou experimentar matar o ouvinte quando não for mais necessário.

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

Eu uni # 379 e liberei para beta8 . Por favor, tente isso.

Isso foi corrigido na versão mais recente? É seguro atualizar para o mais recente?

@hyochan esse problema ainda aparece no 3.0.0-rc-2 alguma ideia?

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 Você poderia tentar 3.0.0-rc-4 ? Vai funcionar perfeitamente (espero).

@hyochan Se eu usar try catch esse erro de runtime não ocorrerá, acho que o rc-4 deve resolver isso.
Obrigado !

Esta página foi útil?
0 / 5 - 0 avaliações