52 votes

API de facturation v3 IabHelper NullPointerException

edit 4/15 : La capture de nullpointer dans IabHelper semble avoir mis fin à ce problème. Je ne vois plus les exceptions lancées, je vais accepter cela comme une réponse.


edit 4/04 : Un peu plus loin dans le détail. Il y a des blocs try catch qui gèrent les RemoteExceptions et les JSONExceptions pour la méthode queryPurchases, mais pas de gestion des NullPointerExceptions. Ce que je vais essayer de faire, c'est d'inclure la gestion des exceptions NullPointer afin que l'IabHelper ressemble à ceci lorsqu'il essaie d'interroger la méthode querySkuDetails :

    catch (NullPointerException e) {
        throw new IabException(IABHELPER_UNKNOWN_ERROR, "NullPointer while refreshing inventory.", e);
    }

Je viens de déposer un bug à ce sujet :

https://code.google.com/p/marketbilling/issues/detail?id=114


edit 3/25 : Eh bien, je reçois toujours ce plantage... maintenant il se produit en essayant d'obtenir un contexte à la ligne 3 de l'extrait suivant de IabHelper :

int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {
    logDebug("Querying owned items, item type: " + itemType);
    logDebug("Package name: " + mContext.getPackageName());

C'est frustrant car dans mon manifeste, j'utilise toujours le nom complet du chemin d'accès de mon application pour "nom".

Exemple "com.myappname.blah.ClassName"

J'ai également essayé de passer ceci, MyClass.this, getApplicationContext() à mHelper. Cependant, ils produisent tous les mêmes résultats NullPointer au hasard des appareils dans la nature. J'ai également essayé de nommer ".MyClass" dans le manifeste. Voici à quoi cela ressemble actuellement :

mHelper = new IabHelper(MyClass.this, myKey);

modifier 18/03/13 : Je reçois toujours des exceptions, même avec la nouvelle version de IabHelper déployée le 17/03.

Je commence à voir un modèle ici, que les pannes sont toutes en essayant d'obtenir un contexte lors de l'exécution de mContext.getPackageName(). Je suis curieux de savoir pourquoi cela fonctionne sur tous mes appareils de test, alors que je n'arrive pas à reproduire ce plantage, qui ne semble concerner qu'un petit nombre d'appareils.

Voici le nouveau crash :

java.lang.NullPointerException
    at com.myapp.util.IabHelper.queryPurchases(SourceFile:836)
    at com.myapp.util.IabHelper.queryInventory(SourceFile:558)
    at com.myapp.util.IabHelper.queryInventory(SourceFile:522)
    at com.myapp.util.IabHelper$2.run(SourceFile:617)
    at java.lang.Thread.run(Thread.java:1019)

Causé par IabHelper...

line 836: logDebug("Package name: " + mContext.getPackageName());

modifier 3/17/13 : Je vois qu'il y a eu de nombreuses corrections de bugs publiées au cours des derniers mois, je vais essayer le dernier code disponible ici et voir si cela résout le problème :

https://code.google.com/p/marketbilling/source/browse/v3/src/com/example/Android/trivialdrivesample/util


Dans l'une de mes applications, j'utilise l'API de facturation et le code passe-partout qui l'accompagne.

J'utilise la dernière version de l'API de facturation disponible via le gestionnaire de SDK à la date du 16 mars 2013.

Dans mon activité, j'interroge l'inventaire en utilisant ce qui suit :

final List<String> skuList = new ArrayList<String>();
skuList.add("sku1");
skuList.add("sku2");
skuList.add("sku3");
if (skuList != null) {
    if (skuList.size() > 0) {
        try {
            mHelper.queryInventoryAsync(true, skuList, mGotInventoryListener);
        } catch (Exception e) { 
            ACRA.getErrorReporter().handleException(e);
        }
    }
}

Je reçois plusieurs rapports NullPointerException dans la nature de la classe IabHelper pour les dispositifs suivants. Je n'arrive pas à reproduire le problème et je ne trouve aucune information concernant ces pannes. C'est la raison pour laquelle je poste cette question.

Je dispose d'un nombre incalculable d'autres vérifications des nuls et des blocs try/catch dans la partie de l'API de facturation qui s'adresse aux développeurs, y compris dans onQueryInventoryFinished. Je sais donc que cette exception n'est pas levée depuis "mon code" (car je ne capture pas les plantages dans les classes de mon application), mais qu'elle est levée depuis l'IabHelper lui-même. Je n'ai pas modifié l'IabHelper en dehors de cette correction recommandée : http://stackoverflow.com/a/14737699

Crash #1 Galaxy Nexus

java.lang.NullPointerException
    at com.myapp.util.IabHelper.querySkuDetails(SourceFile:802)
    at com.myapp.util.IabHelper.queryInventory(SourceFile:471)
    at com.myapp.util.IabHelper$2.run(SourceFile:521)
    at java.lang.Thread.run(Thread.java:856)

Causé par IabHelper...

line 802: Bundle skuDetails = mService.getSkuDetails(3, mContext.getPackageName(), ITEM_TYPE_INAPP, querySkus);    

Crash #2 Samsung GT-S5570L

java.lang.NullPointerException
    at com.myapp.util.IabHelper.queryPurchases(SourceFile:735)
    at com.myapp.util.IabHelper.queryInventory(SourceFile:465)
    at com.myapp.util.IabHelper$2.run(SourceFile:521)
    at java.lang.Thread.run(Thread.java:1019)

Causé par IabHelper...

line 735: Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(), ITEM_TYPE_INAPP, continueToken);

24voto

logray Points 1249

edit 4/15 : La capture de nullpointer dans IabHelper semble avoir mis fin à ce problème. Je ne vois plus les exceptions lancées, je vais accepter cela comme une réponse.


edit 4/04 : Une plongée un peu plus profonde. Il y a des blocs try catch qui gèrent les RemoteExceptions et les JSONExceptions pour la méthode queryPurchases, mais pas de gestion des NullPointerExceptions. Ce que je vais essayer de faire, c'est d'inclure la gestion des exceptions NullPointer afin que l'IabHelper ressemble à ceci lorsqu'il essaie d'interroger la méthode querySkuDetails :

    catch (NullPointerException e) {
        throw new IabException(IABHELPER_UNKNOWN_ERROR, "NullPointer while refreshing inventory.", e);
    }

Je viens de déposer un bug à ce sujet :

https://code.google.com/p/marketbilling/issues/detail?id=114

20voto

tmanthey Points 1887

Vous utilisez probablement des opérations asynchrones. L'IabHelper actuel n'est pas sûr dans le cas où vous utilisez les méthodes ...async. Le problème est qu'à chaque fois qu'une opération async est en cours d'exécution, dispose peut être appelé sur le thread principal. Dans ce cas, vous obtiendrez des exceptions NullPointerExceptions et IllegalStateExceptions.

Voici le patch qui le corrige :

Index: src/com/evotegra/aCoDriver/iabUtil/IabHelper.java
===================================================================
--- src/com/evotegra/aCoDriver/iabUtil/IabHelper.java   (revision 1162)
+++ src/com/evotegra/aCoDriver/iabUtil/IabHelper.java   (working copy)
@@ -86,7 +86,10 @@

     // Is an asynchronous operation in progress?
     // (only one at a time can be in progress)
-    boolean mAsyncInProgress = false;
+    volatile boolean mAsyncInProgress = false;
+    
+    // is set to true if dispose is called while a thread is running. Allows graceful shutdown
+    volatile boolean mDisposeRequested = false;

     // (for logging/debugging)
     // if mAsyncInProgress == true, what asynchronous operation is in progress?
@@ -285,6 +288,12 @@
      * disposed of, it can't be used again.
      */
     public void dispose() {
+       // do not dispose while an async Thread is running. Will cause all kinds of exceptions.
+       // In this case dispose must be called from thread after setting mAsyncInProgress to true
+       if (mAsyncInProgress) {
+           mDisposeRequested = true;
+           return;
+       }
         logDebug("Disposing.");
         mSetupDone = false;
         if (mServiceConn != null) {
@@ -827,6 +836,7 @@
         logDebug("Ending async operation: " + mAsyncOperation);
         mAsyncOperation = "";
         mAsyncInProgress = false;
+        if (mDisposeRequested) IabHelper.this.dispose();
     }

Ou téléchargez le patch ici. http://code.google.com/p/marketbilling/issues/detail?id=139&thanks=139&ts=1375614409

0voto

Thunder Points 265

Modifiez légèrement le début de la queryPurchases pour ressembler à ceci :

int queryPurchases(Inventory inv, String itemType) throws JSONException, RemoteException {
        // Query purchases
        //logDebug("Querying owned items, item type: " + itemType);
       //logDebug("Package name: " + mContext.getPackageName());
       boolean verificationFailed = false;
       String continueToken = null;

        do {
//            logDebug("Calling getPurchases with continuation token: " + continueToken);
            if(mDisposed || mService==null) return IABHELPER_UNKNOWN_ERROR;
            Bundle ownedItems = mService.getPurchases(3, mContext.getPackageName(),
                    itemType, continueToken);

Merci à sebastie pour avoir indiqué la cause de ce problème.

0voto

tmanthey patch exige également

mDisposeRequested = false;

après que l'élimination a eu lieu

-1voto

sandalone Points 8326

Si vous obtenez cette erreur sur l'émulateur, il peut s'agir d'une chose très simple qui se produit dans plus de la moitié des cas.

Vérifiez que vous utilisez le SDK de l'API Google et non le SDK normal ! !!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X