sincronizar sincronizacion sincroniza significa qué puedo produciendo problemas porque google estan error cuenta correo con celular automaticamente android android-billing

sincronizacion - Facturación en la aplicación de Android: no se puede iniciar la operación de sincronización porque otra operación de sincronización(está en progreso)



sincronizar celular (18)

Asegúrese de llamar a handleTactivityResult de handleActivityResult en el ActivityActivityResult, y NO en onActivityResult de onActivityResult .

El siguiente fragmento de código es de MainActivity de MainActivity :

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.d(TAG, "onActivityResult(" + requestCode + "," + resultCode + "," + data); if (mHelper == null) return; // Pass on the activity result to the helper for handling if (!mHelper.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."); } }

Actualizar:

Estoy usando las clases de utilidad IabHelper , tal como lo recomienda el tutorial de Google, y me está golpeando mucho este error. Aparentemente IabHelper no puede ejecutar múltiples operaciones asíncronas al mismo tiempo. Incluso logré golpear tratando de comenzar una compra mientras la toma de inventario todavía estaba en progreso.

Ya he intentado implementar onActivityResult en mi clase principal como se sugiere here , pero ni siquiera recibo una llamada a ese método antes de que el error llegue. Luego encontré this pero no tengo idea de dónde encontrar este método flagEndAsync , no está en la clase IabHelper .

Ahora estoy buscando una forma de evitar esto (sin volver a implementar todo el She-Bang). La única solución que se me ocurre es crear un campo booleano asyncActive que esté marcado antes de iniciar una tarea asíncrona, y no hacerlo si hay otra tarea activa. Pero eso tiene muchos otros problemas y no funciona en todas las actividades. También preferiría tener una cola de tareas asíncronas y ejecutar tan pronto como se permite, en lugar de no ejecutar en absoluto.

¿Alguna solución para este problema?


Encuentra flagEndAsync() dentro del archivo IabHelper.java y haz que sea una función pública .

Antes de intentar comprar llame a flagEndAsync() para su IabHelper .

debes hacer algo así como este código:

mHelper.flagEndAsync(); mHelper.launchPurchaseFlow(AboutActivity.this, SKU_PREMIUM, RC_REQUEST, mPurchaseFinishedListener, "payload-string");


Esta respuesta aborda directamente el problema que @Wouter ha visto ...

Es cierto que onActivityResult() debe onActivityResult() , como muchas personas han dicho. Sin embargo, el error es que el código de Google no está activando onActivityResult() en ciertas circunstancias, es decir, cuando presiona el botón [COMPRAR] dos veces al ejecutar la compilación de depuración de su aplicación.

Además, uno de los principales problemas es que el usuario puede estar en un entorno inestable (es decir, en el autobús o el metro) y presiona dos veces el botón [COMPRAR] ... ¡de repente tiene una excepción!

Al menos Google solucionó esta embarazosa excepción https://github.com/googlesamples/android-play-billing/commit/07b085b32a62c7981e5f3581fd743e30b9adb4ed#diff-b43848e47f8a93bca77e5ce95b1c2d66

A continuación se muestra lo que implementé en la misma clase donde IabHelper está instanciado (para mí, esto es en la clase de aplicación):

/** * invokes the startIntentSenderForResult - which will call your activity''s onActivityResult() when it''s finished * NOTE: you need to override onActivityResult() in your activity. * NOTE2: check IAB code updates at https://github.com/googlesamples/android-play-billing/tree/master/TrivialDrive/app/src/main/java/com/example/android/trivialdrivesample/util * @param activity * @param sku */ protected boolean launchPurchaseWorkflow(Activity activity, String sku) { if (mIabIsInitialized) { try { mHelper.launchPurchaseFlow( activity, sku, Constants.PURCHASE_REQUEST_ID++,// just needs to be a positive number and unique mPurchaseFinishedListener, Constants.DEVELOPER_PAYLOAD); return true;//success } catch (IllegalStateException e) { mHelper.flagEndAsync(); return launchPurchaseWorkflow(activity, sku);//recursive call } } else { return false;//failure - not initialized } }

Mi botón [COMPRAR] llama a este launchPurchaseWorkflow() y pasa el SKU y la actividad en la que se encuentra el botón (o si está en un fragmento, la actividad adjunta)

NOTA: asegúrese de hacer que IabHelper.flagEndAsync() público.

Con suerte, Google mejorará este código en el futuro cercano; este problema tiene unos 3 años y sigue siendo un problema constante :(


Estaba teniendo el mismo problema hasta que tropecé con otro hilo SO . Incluyo una versión retocada del código que se encuentra en el otro hilo que debe incluir en su Actividad que inicia la compra.

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Pass on the activity result to the helper for handling // NOTE: handleActivityResult() will update the state of the helper, // allowing you to make further calls without having it exception on you if (billingHelper.handleActivityResult(requestCode, resultCode, data)) { Log.d(TAG, "onActivityResult handled by IABUtil."); handlePurchaseResult(requestCode, resultCode, data); return; } // What you would normally do // ... }


Esto no fue fácil de descifrar pero encontré las soluciones alternativas necesarias. Muy decepcionados con Google últimamente, sus sitios web Android se han convertido en un desastre (es muy difícil encontrar información útil) y su código de muestra es pobre. Cuando hacía algunos años desarrollaba Android, ¡todo fue mucho más fácil! Este es otro ejemplo más de eso ...

De hecho, IabUtil tiene errores, no cancela sus propias tareas asincrónicas. El conjunto completo de soluciones temporales necesarias para estabilizar esta cosa:

1) hacer que el método flagEndAsync público. Está allí, simplemente no visible.

2) haga que cada oyente llame a iabHelper.flagEndAsync para asegurarse de que el procedimiento esté marcado como terminado correctamente; parece ser necesario en todos los oyentes.

3) llamadas de sonido envolvente con un try/catch para atrapar la IllegalStateException que puede ocurrir, y manejarlo de esa manera.


He tenido este problema ocasionalmente, y en mi caso lo he rastreado hasta el hecho de que si el método onServiceConnected en IabHelper se puede llamar más de una vez si el servicio subyacente se desconecta y se vuelve a conectar (por ejemplo, debido a una conexión de red intermitente).

Las operaciones específicas en mi caso fueron "No se puede iniciar la operación asincrónica (actualizar el inventario) porque otra operación asincrónica (launchPurchaseFlow) está en progreso".

La forma en que está escrita mi aplicación, no puedo llamar a launchPurchaseFlow hasta que haya completado un queryInventory, y solo llamo queryInventory desde mi función de controlador onIabSetupFinished.

El código IabHelper llamará a esta función de controlador siempre que se llame a onServiceConnected, lo que puede suceder más de una vez.

La documentación de Android para onServiceDisconnected dice:

Se invoca cuando se pierde una conexión al Servicio. Esto generalmente ocurre cuando el proceso que aloja el servicio se ha bloqueado o ha sido eliminado. Esto no elimina ServiceConnection en sí mismo: este enlace al servicio permanecerá activo y recibirá una llamada a onServiceConnected (ComponentName, IBinder) cuando se ejecute el servicio.

que explica el problema.

Podría decirse que IabHelper no debería llamar a la función de escucha onIabSetupFinished más de una vez, pero, por otro lado, era trivial solucionar el problema en mi aplicación simplemente no llamando a queryInventory desde esta función si ya lo hice y obtuve los resultados .


Mi solución es simple

1.) Haga visible la variable mAsyncInProgress fuera de IabHelper

public boolean isAsyncInProgress() { return mAsyncInProgress; }

2.) Usa esto en tu Actividad como:

... if (mIabHelper.AsyncInProgress()) return; mIabHelper.queryInventoryAsync(...); ...


O bien, puede obtener el último archivo IabHelper.java aquí: code.google.com/p/marketbilling/source/browse

La versión del 15 de marzo me solucionó esto. (Tenga en cuenta que otros archivos sin cambios fueron confirmados el día 15)

Aún tuve que arreglar un bloqueo que ocurrió durante las pruebas causado por un intento nulo de extras cuando "android.test.canceled" era el SKU enviado. Cambié:

int getResponseCodeFromIntent(Intent i) { Object o = i.getExtras().get(RESPONSE_CODE);

a:

int getResponseCodeFromIntent(Intent i) { Object o = i.getExtras() != null ? i.getExtras().get(RESPONSE_CODE) : null;


Otro problema importante con la clase IabHelpr es la mala elección de arrojar RuntimeExcptions (IllegalStateException) en múltiples métodos. Lanzar excepciones de Runtime desde su propio código en la mayoría de los casos no es deseable debido a que son excepciones sin marcar . Eso es como sabotear su propia aplicación: si no se detecta, estas excepciones aparecerá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 IllegalStateException. Eso lo forzará a manejar esta excepción en todos los sitios en los que se pueda arrojar su código en tiempo de compilación.

Aquí está 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 hacemos los cambios en la clase IabHelper, podemos manejar nuestra excepción marcada en nuestro código donde llamamos a los métodos de clase. Por ejemplo:

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


Problema realmente molesto. Aquí hay una solución rápida y sucia que no es perfecta para el código, pero que es fácil de usar y evita las malas clasificaciones y bloqueos:

if (mHelper != null) { try { mHelper.launchPurchaseFlow(this, item, RC_REQUEST, mPurchaseFinishedListener, ""); } catch(IllegalStateException ex){ Toast.makeText(this, "Please retry in a few seconds.", Toast.LENGTH_SHORT).show(); } }

De esta forma, el usuario solo tiene que tocar otra vez (2 veces en el peor de los casos) y obtiene la ventana emergente de facturación

Espero eso ayude


Sí, también estoy enfrentando este problema, pero resolví esto pero resolví usar

IabHelper mHelpermHelper = new IabHelper(inappActivity, base64EncodedPublicKey); mHelper.flagEndAsync();

El método anterior detiene todas las banderas. Su trabajo para mí debe verificar


Simplemente verifique el Código de solicitud onActivityResult en la actividad y, si coincide con el PURCHASE_REQUEST_CODE que utilizó en la compra, simplemente páselo al fragmento.

Cuando agrega o reemplaza el fragmento en FragmentTransaction, simplemente configure una etiqueta:

fTransaction.replace(R.id.content_fragment, fragment, fragment.getClass().getName());

Luego en su actividad en ActivityResult

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(requestCode == PurchaseFragment.PURCHASE_REQUEST_CODE) { PurchaseFragment fragment = getSuportFragmentManager().findFragmentByTag(PurchaseFragment.class.getNAme()); if(fragment != null) { fragment.onActivityResult(requestCode, resultCode, data); } } }


Tengo el mismo problema, pero resolvió! Creo que no se debe ejecutar "launchPurchaseFlow" en el hilo de UI, intente ejecutar launchPurchaseFlow en el hilo de UI, ¡estaría funcionando bien!

mActivity.runOnUiThread(new Runnable(){ public void run(){ mHelper.launchPurchaseFlow(mActivity, item, 10001, mPurchaseFinishedListener,username); } });


Terminé haciendo algo similar a Kintaro. Pero agregó mHelper.flagEndAsync () al final de la captura. El usuario todavía recibe el brindis, pero la próxima vez que presione el botón de compra, la operación de sincronización ha sido eliminada y el botón de compra estará listo para continuar.

if (mHelper != null) { try { mHelper.launchPurchaseFlow(this, item, RC_REQUEST, mPurchaseFinishedListener, ""); } catch(IllegalStateException ex){ Toast.makeText(this, "Please retry in a few seconds.", Toast.LENGTH_SHORT).show(); mHelper.flagEndAsync(); } }


Tuve el mismo problema y el problema fue que no implementé el método en ActivityResult.

@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { try { if (billingHelper == null) { return; } else if (!billingHelper.handleActivityResult(requestCode, resultCode, data)) { super.onActivityResult(requestCode, resultCode, data); } } catch (Exception exception) { super.onActivityResult(requestCode, resultCode, data); } }


Un simple truco que lo hizo por mí fue crear un método en IabHelper:

public Boolean getAsyncInProgress() { return mAsyncInProgress; }

y luego en tu código, solo revisa:

if (!mHelper.getAsyncInProgress()) //launch purchase else Log.d(TAG, "Async in progress already..)


Una solución simple y difícil

antes de llamar al método purchaseItem simplemente agregue esta línea

if (billingHelper != null) billingHelper.flagEndAsync();

para que tu código se vea de esta manera

if (billingHelper != null) billingHelper.flagEndAsync(); purchaseItem("android.test.purchased");

Nota: no olvides hacer el método público flagEndAsync () en IabHelper si lo llamas desde otro paquete.


si codifica en fragmento, entonces este código en IabHelper.java

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); }