在Codename中测试应用内购买一个模拟器导致空指针异常

时间:2016-11-08 19:49:57

标签: android in-app-purchase codenameone

我没有创建我的应用程序的灯光和完整版本,而是决定采用免费增值方式,并提供一个按钮,从灯光升级到完整版本。

该应用程序仅适用于Google Play商店。因此,我按照http://mobilecodetogo.blogspot.fr/2013/03/android-does-it-better-in-app-purchase.html所述在Play商店中创建了应用内购买。

以下是我实施的代码:

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

ParametresGeneraux.getPurchase()正在做Purchase.getInAppPurchase()的地方。

当我在带有Android皮肤(Nexus 5)的模拟器上测试时,列表未显示,并且在执行购买后总是会导致空指针异常:

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)

相反,在提交应用程序几小时后在设备上,将收取购买费用(因此找到项目并且不为空)。但是,当我重新启动应用程序时,它仍处于轻型版本。

以下是我如何测试它是否是轻型版本(在主类的init方法中):

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

根据这个2014 SO问题(以及之后关闭的提到的RFE),我认为wasPurchased也适用于Android。所以我不知道它为什么不起作用。

其实我的问题是:

是否可以使用模拟器在应用程序购买中进行测试?

wasPurchased是否有正确的方法来检查用户是否已购买该功能?

非常感谢你给我提示!

2 个答案:

答案 0 :(得分:1)

模拟器无法连接到Google Play并且可以为您期望的内容返回null。请注意,有API表示支持项目列表等事项。

您可以通过模拟器菜单操作购买API的某些元素。

答案 1 :(得分:0)

因此,为了摆脱在模拟器中返回purchase()方法后出现的NPE,主类必须实现PurchaseCallback接口 !!!

Main CN1类是具有start()和init()方法的类,而不是状态机,如[Shai] [2]所示。这是一个至关重要的部分,应该在[购买教程] [3]中强调,尽管这在API文档中写得很好:

  

公共接口PurchaseCallback   主类必须实现的回调接口才能使应用内购买工作。一旦主类实现此接口,就会调用其中的方法来指示各种购买状态。

现在,当itemPurchased()返回后,将调用PurchaseCallback实现中的purchase()方法。模拟器在CN1InAppPurchases文件(Linux上的.cn1文件夹)中跟踪购买情况。

此外,现在已经实现了PurchaseCallback,在模拟器中(不在Android设备上),wasPurchased()方法根据先前的purchase()调用返回预期值成功了。