Android In-App Billing v3: "No se puede realizar la operación: queryInventory"

Tengo la configuración de facturación en la aplicación por primera vez utilizando la nueva API v3. Está funcionando correctamente en mis dispositivos, pero he recibido una gran cantidad de informes de errores de otros usuarios.

Uno de ellos es:

java.lang.IllegalStateException: IAB helper is not set up. Can't perform operation: queryInventory at my.package.util.iab.IabHelper.checkSetupDone(IabHelper.java:673) at my.package.util.iab.IabHelper.queryInventory(IabHelper.java:462) at my.package.util.iab.IabHelper$2.run(IabHelper.java:521) at java.lang.Thread.run(Thread.java:1019) 

Y otro es:

 java.lang.NullPointerException at my.package.activities.MainActivity$4.onIabSetupFinished(MainActivity.java:159) at my.package.util.iab.IabHelper$1.onServiceConnected(IabHelper.java:242) 

Mi implementación de actividad sigue el código de ejemplo de Google (todas las clases referenciadas no están afectadas por el ejemplo):

 IabHelper mHelper; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //... mHelper = new IabHelper(this, IAB_PUBLIC_KEY); mHelper.enableDebugLogging(true); mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { if (!result.isSuccess()) { // Oh noes, there was a problem. return; } // Hooray, IAB is fully set up. Now, let's get an inventory of // stuff we own. mHelper.queryInventoryAsync(mGotInventoryListener); //***(1)*** } }); } // Listener that's called when we finish querying the items we own IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { if (!result.isFailure()) { if (inventory.hasPurchase(SoundsGlobals.IAB_SKU_PREMIUM)){ //we are premium, do things } } else{ //oops } } }; @Override protected void onDestroy() { if (mHelper != null) { mHelper.dispose(); mHelper = null; } super.onDestroy(); } 

Supongo que ambos errores se originan en la línea marcada como ***(1)***

¿Cuál es la causa de estos errores? Si estoy llamando a queryInventoryAsync sólo en onIabSetupFinished , ¿cómo es posible que mHelper sea ​​nulo o que mHelper no esté configurado?

¿Alguien sabe una solución a esto?

Como explicó @Martin, hubo un error en el ejemplo de facturación de Google In-App que causó esto.

Sin embargo, después de arreglarlo, seguía recibiendo algunos errores en las llamadas internas ( queryInventory dentro del subproceso creado en queryInventoryAsync en algunos casos raros de informes de que el ayudante no está configurado). He resuelto esto añadiendo una captura adicional en ese caso:

 try { inv = queryInventory(querySkuDetails, moreSkus); } catch (IabException ex) { result = ex.getResult(); } catch(IllegalStateException ex){ //ADDED THIS CATCH result = new IabResult(BILLING_RESPONSE_RESULT_ERROR, "Helper is not setup."); } 

También conseguí un choque en mHelper.dispose() que mHelper.dispose() una manera similar:

 try{ if (mContext != null) mContext.unbindService(mServiceConn); } catch(IllegalArgumentException ex){ //ADDED THIS CATCH //IGNORE IT - somehow, the service was already unregistered } 

Por supuesto, en lugar de ignorar estos errores se pueden registrar en silencio a ACRA, por ejemplo 🙂

Gracias por todos sus comentarios.

Hay un error en IABHelper. La línea de retorno en el manejador de excepciones falta, lo que significa que cae a través y llama al éxito hanlder – sin embargo, mSetupDone no se ha establecido, por lo que más llamadas a la API fallan. Agregue la declaración de devolución en como a continuación – esto todavía fallará, pero el error se informará correctamente a su aplicación para que pueda tomar la acción apropiada.

  catch (RemoteException e) { if (listener != null) { listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, "RemoteException while setting up in-app billing.")); } e.printStackTrace(); return; // This return line is missing } if (listener != null) { listener.onIabSetupFinished(new IabResult(BILLING_RESPONSE_RESULT_OK, "Setup successful.")); } 

Creo que todavía hay dos errores en el código de Android, lo que explica por qué sigue viendo el error. Observe que la pila de llamadas se encuentra en un subproceso autónomo. Pero el código que establece mSetupDone (IabHelper) en true se ejecuta en el subproceso de interfaz de usuario principal. Java no garantiza que los datos cambiados por un hilo sean visibles para el otro hilo debido al almacenamiento en caché de la CPU a menos que declare la variable con la palabra clave volátil. Por lo tanto, es posible que se haya configurado (mSetupDone == true), pero que el nuevo valor de mSetupDone se almacena en caché en el subproceso de UI, aún no visible para este subproceso en la pila de llamadas. De modo que el hilo sigue viendo mSetupDone == false.

Traté de arreglar esto declarando mSetupDone con volátil, y también todos los demás campos no-final de IabHelper sólo para estar seguro.

Ahora el otro problema es la función .dispose (). No detiene los hilos en curso. Esto significa que puede establecer mSetupDone a false mientras se ejecuta uno de los subprocesos de trabajo. Si observa queryInventoryAsync (), verá que comprueba que mSetupDone es true. Y en base a su pila de llamadas, se superó. Luego se estrelló más tarde con mSetupDone == false. La única manera que podría suceder es si disponen () fueron llamados mientras su hilo estaba en vuelo. Corrección es que dispose () necesita señalar los hilos para rescatar silenciosamente en lugar de continuar y lanzar errores cuando ve mSetupDone == false. Esto también evita otro problema con IabHelper donde las instancias dispuestas llaman callbacks del oyente incluso después de haber sido eliminadas. Es un poco complicado de explicar línea por línea aquí, pero espero que así te hace señalar en la dirección correcta.

¡Lo descubrí! Se trata de la versión de la aplicación Google Play Store del usuario. La facturación en la aplicación V3 necesita 3.9.16 o superior ( http://developer.android.com/google/play/billing/versions.html ). He utilizado una versión anterior y he recibido ese error, ahora en 4.4.21 su ok!

Asegúrese de que está implementando el IabHelper.han.handleActivityResult(requestCode, resultCode, data) en su método onActivityResult actividades.

  @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // Pass on the activity result to the helper for handling if (!mIabHelper.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.i(TAG, "onActivityResult handled by IABUtil."); } } 

Estoy recibiendo ese mismo error EXACTO con bastante-mucho el mismo código exacto.

Sólo parece estar sucediendo en ciertos teléfonos (en realidad, parece casi exclusivamente el Tablet Acer Iconia en los últimos informes de error!) – y estoy manejando onActivityResult …

Hay un número de errores en la muestra de la facturación de Google v3 que puede causar ANRs / FCs – sospecho que esto es apenas otro (el código de mala calidad y los documentos de mala calidad se están convirtiendo en una marca registrada de Google – tristemente).

Mi suposición es, por ahora, que debemos permitir que mHelper o mGotInventoryListener sean nulos y simplemente desactivar la facturación en la aplicación en ese caso (como si result.isSuccess () fuera falso, básicamente)

Ps editted para agregar – sólo podría ser que el usuario tiene una versión desactualizada de la Play Store – que sólo se actualiza automáticamente si permiten que se ejecute !?

Puede mantenerse al día con el desarrollo de la API inapp v3 en https://code.google.com/p/marketbilling/

El código allí es más nuevo que el que está disponible a través del SDK Manager de Android.

Además de @DavidM y @Ereza.

Otro problema importante con la clase IabHelpr es la mala elección de ejecutar RuntimeExcptions (IllegalStateException) en varios métodos. Lanzar RuntimeExeptions de su propio código en la mayoría de los casos no es deseable debido al hecho de que son excepciones no comprobadas . Eso es como sabotear su propia aplicación, si no es capturada, estas excepciones se burbujearán y bloquearán su aplicación.

La solución a esto es implementar su propia excepción comprobada y cambiar la clase IabHelper para lanzarla, en lugar de la excepción IllegalStateException. Eso te obligará a manejar esta excepción en todas partes que podría ser lanzado en su código en tiempo de compilación.

Esta es mi excepción personalizada:

 public class MyIllegalStateException extends Exception { private static final long serialVersionUID = 1L; //Parameterless Constructor public MyIllegalStateException() {} //Constructor that accepts a message public MyIllegalStateException(String message) { super(message); } } 

Una vez que realizamos los cambios en la clase IabHelper, podemos manejar nuestra excepción seleccionada en nuestro código en la que llamamos a los métodos de clase. Por ejemplo:

 try { setUpBilling(targetActivityInstance.allData.getAll()); } catch (MyIllegalStateException ex) { ex.printStackTrace(); } 

Si todo lo anterior no le ayuda, intente analizar su código un poco – ¿ es su IabHelper realmente configurado en el momento en que lo está llamando?

Me encontré haciendo un poco mal sin darse cuenta. Un ejemplo sencillo de usarlo incorrecto en Activity.onCreate()

 m_iabHelper = new IabHelper(this, base64EncodedPublicKey); // Declare m_iabHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { // Setup public void onIabSetupFinished(IabResult result) { // Setup code } } // Don't do this, will produce an error List additionalSkuList = new ArrayList(); additionalSkuList.add(SKU_MYSKU); m_iabHelper.queryInventoryAsync(true, additionalSkuList, m_queryFinishedListener); // Don't do this, will produce an error 

.

Arriba lo m_iabHelper.queryInventoryAsync() el error "IAB helper is not set up" ya que mientras tu aplicación intenta ejecutar m_iabHelper.queryInventoryAsync() , el IabHelper no está configurado todavía. Considere el uso de estas funciones en onIabSetupFinished() o en algún lugar después de que la función se llama (por ejemplo, fuera de la onCreate() )

Tengo los mismos errores. También me encontré con otros temas …

Tener más de una cuenta de Google en un dispositivo deshabilitado en la aplicación de facturación en mi Galaxy Tab 7. Quitar una cuenta habilitada de nuevo.

He visto problemas con el código de ejemplo de facturación de aplicación en un GT-P5110, LGL75C y GT-S5839i, entre otros.

(Yo uso el código en una aplicación con ACRA instalado … así que cada vez que se bloquea, obtengo información)

Los dispositivos de la versión de Android varía de 2.3.3 a 4.0.4.

Es muy molesto.

Hubo muchos problemas con IABHelper.java.

En primer lugar, la versión descargada por SDK Manager no se actualiza. Utilice la versión que se encuentra aquí: https://code.google.com/p/marketbilling/source/detail?r=15946261ec9ae5f7c664d720f392f7787e3ee6c7 Es la versión más actualizada al publicar esta respuesta. Muchos problemas parecen haberse solucionado con esta versión en comparación con la versión inicial que viene del SDK Manager.

Lo único que he tenido que cambiar en esta versión es añadir flagEndAsync(); Después de la línea 404 que corrige una IllegalStateException cuando 2 flujos de compra IAB se inician en sucesión rápida.

Con esta versión no es necesario administrar usando flagEndAsync(); En sus archivos y puede dejar el método para no ser público.

  • IInAppBillingService mostrar una advertencia - método getInterfaceDescriptor nunca se utiliza localmente - ¿Cómo eliminar?
  • En la API de facturación de la aplicación v3 INAPP_PURCHASE_DATA es nulo en el paquete cuando onActivityResult se llama
  • Cómo crear una compra en la aplicación para actualizar la versión gratuita a la versión de pago de Android
  • El artículo que usted pidió no está disponible para la compra
  • Facturación en la aplicación: "Elementos de consulta disponibles para la compra" devuelve 0 artículos
  • Cómo corregir - "Esta versión de la aplicación no está configurada para la facturación de mercado"?
  • No puede hacer que la aplicación de ejemplo de facturación de Android en la aplicación funcione
  • En el módulo BillingService, ¿qué necesita modificarse para aumentar la seguridad?
  • Facturación en la aplicación: Error: su pago no se pudo procesar en este momento
  • IAB firmó datos sin órdenes en él
  • Cancelar o reembolsar la compra consumida en la aplicación en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.