Test In-App-Purchase in Codename One simulator results in Null Pointer Exception

风格不统一 提交于 2019-12-10 11:43:37

问题


Instead of creating a light and a full version of my app, I decided to go the freemium way and offer a button to upgrade from the light to the full version.

The application is only available on the Google Play Store. So I created an in app purchase in the Play Store as described http://mobilecodetogo.blogspot.fr/2013/03/android-does-it-better-in-app-purchase.html.

Here is the code that I implemented :

if (buyFull) {

              if (ParametresGeneraux.getPurchase().isManagedPaymentSupported()) {
                  String[] skus = {"ParametresGeneraux.getFullVersionSKU()"};

                   if (ParametresGeneraux.getPurchase().isItemListingSupported()) {
                     Product[] products = ParametresGeneraux.getPurchase().getProducts(skus);
                     String items = "";

                     if (products != null) {
                       for (Product p : products) {
                          items += p.getDescription();
                       }
                     }

                     Dialog.show("Produits intégrés", "Les produits intégrés sont " + items,
                                                         "OK", "Cancel");
                 }

                 // On achète
                 ParametresGeneraux.getPurchase().purchase("ParametresGeneraux.getFullVersionSKU()");
           } else {
                   Dialog.show("Évolution impossible", "Impossible d'évoluer vers la version complète. Votre compte n'a pas été débité.", "OK", "Compris");
                  }

Where ParametresGeneraux.getPurchase() is doing Purchase.getInAppPurchase().

When I test it on the simulator with an Android skin (Nexus 5) the listing is not shown and it always results in a null pointer exception after executing the purchase :

java.lang.NullPointerException
at com.codename1.impl.javase.JavaSEPort$82$5$1.run(JavaSEPort.java:7936)
at com.codename1.ui.Display.processSerialCalls(Display.java:1152)
at com.codename1.ui.Display.edtLoopImpl(Display.java:1096)
at com.codename1.ui.Display.mainEDTLoop(Display.java:997)
at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120)
at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)

On the contrary on the device few hours after submitting the app, the purchase is charged (so item is found and not null). However when I restart the app it is still in light version.

Here is how I test if it is a light version (in the init method from the main class) :

    ParametresGeneraux.setPurchase(Purchase.getInAppPurchase());
    ParametresGeneraux.setLightVersion(true);
    if (ParametresGeneraux.getPurchase().isManagedPaymentSupported()) {
        if (ParametresGeneraux.getPurchase().wasPurchased(ParametresGeneraux.getFullVersionSKU())) {
            ParametresGeneraux.setLightVersion(false);
        }
    } 

According to this 2014 SO question (and the mentioned RFE that has been closed since then) I assume wasPurchased should also work on Android. So I don't know why it does not work.

Actually my questions are :

Is it possible to test in app purchase with the simulator ?

Is wasPurchased the right method to pick up to check whether the user has bought the feature ?

Thanks a lot for giving me hints!


回答1:


The simulator doesn't connect to google play and can return null for things you expect to be there. Notice that there are API's that indicate things such as if item listing is supported etc.

You can manipulate some elements of the purchase API via the simulator menu.




回答2:


So to get rid of the NPE that appears right after the purchase() method returns in the simulator, the main class MUST implement PurchaseCallback interface!!!

The Main CN1 class is the one with the start() and init() methods not the state machine as [indicated by Shai][2]. This is a crucial part and should be stressed in the [Purchase tutorial][3] although this is well written in the API documentation :

public interface PurchaseCallback Callback interface that the main class must implement in order for in-app-purchasing to work. Once the main class implements this interface the methods within it are invoked to indicate the various purchase states.

Now the itemPurchased() method from the PurchaseCallback implementation gets called when the after purchase() returns. And the simulator keeps track of the purchase in the CN1InAppPurchases file (.cn1 folder on Linux).

Furthermore now that the PurchaseCallback has been implemented, in the simulator (not on the Android device however) the wasPurchased() method returns the expected value depending on whether or not a previous purchase() call succeeded.



来源:https://stackoverflow.com/questions/40495272/test-in-app-purchase-in-codename-one-simulator-results-in-null-pointer-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!