libgdx/gdx-pay

PurchaseManagerGoogleBilling: Problem restoring purchases unless entire history of IAPs are listed in PurchaseManagerConfig, even if IAP does not exist in Play Console

alexbooth opened this issue · 8 comments

Problem

Using PurchaseManagerGoogleBilling I'm running into an issue while I'm trying to test purchases of entitlements.

I created an IAP in the play console and then was able to successfully purchase in the game. However, entitlements cannot be purchased again, and there is no way to delete history of in-app purchases to do so (apparently some people have this option in the play store, but this is not the case for me).

I want to be able to test a purchase of an IAP again, but the only way I can is if I create another IAP in the Play Console. Now I'm ending up with a chunk of code as follows because deleting any line causes a NullPointerException.

var purchaseManager = PurchaseManagerGoogleBilling(activity)

fun install() {
    val pmc = PurchaseManagerConfig()
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads"))
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads2"))
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads3"))
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads4"))
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads5"))
    purchaseManager.install(this, pmc, true)
}

override fun handleInstall() {
    purchaseManager.purchaseRestore()
}

Error

A NullPointerException is thrown unless I list the complete history of every entitlement that has been purchased for this app, even if that IAP does not exist in the Play Console anymore. I'm done with testing and want the code below, but this causes a crash.

var purchaseManager = PurchaseManagerGoogleBilling(activity)

fun install() {
    val pmc = PurchaseManagerConfig()
    pmc.addOffer(Offer().setType(OfferType.ENTITLEMENT).setIdentifier("remove.ads"))
    purchaseManager.install(this, pmc, true)
}

override fun handleInstall() {
    purchaseManager.purchaseRestore()
}
Process: com.xxx.xxx, PID: 8896
    java.lang.NullPointerException: Attempt to invoke virtual method 'com.badlogic.gdx.pay.OfferType com.badlogic.gdx.pay.Offer.getType()' on a null object reference
        at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.handlePurchase(PurchaseManagerGoogleBilling.java:246)
        at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.access$700(PurchaseManagerGoogleBilling.java:41)
        at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling$4.onPurchaseHistoryResponse(PurchaseManagerGoogleBilling.java:195)
        at com.android.billingclient.api.BillingClientImpl$4$1.run(BillingClientImpl.java:493)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

The code crashes on the first line of this code block in PurchaseManagerGoogleBilling.java

if (config.getOffer(purchase.getSku()).getType().equals(OfferType.CONSUMABLE)) {
    mBillingClient.consumeAsync(purchase.getPurchaseToken(), new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(@BillingClient.BillingResponse int responseCode, String outToken) {
            if (responseCode == BillingClient.BillingResponse.OK) {
                // handlepurchase is done before item is consumed for compatibility with other
                // gdx-pay implementations
                //TODO what to do if it did not return OK?
            }
        }
    });
}

Thank you. This can be fixed by adding a null-check on config.getOffer(purchase.getSku())

I'm not sure that my errors concerns this issue. But I'll leave it here, maybe the error is the same, there was still no time to figure it out.
I started to get such exceptions:

java.lang.NullPointerException: 
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.access$600 (PurchaseManagerGoogleBilling.java)
  or                     .setInstalledAndNotifyObserver (PurchaseManagerGoogleBilling.java)
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.access$200 (PurchaseManagerGoogleBilling.java)
  or                     .purchaseRestore (PurchaseManagerGoogleBilling.java)
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling$3.onSkuDetailsResponse (PurchaseManagerGoogleBilling.java)
  at com.android.billingclient.api.BillingClientImpl$2$1.run (BillingClientImpl.java)
  at android.os.Handler.handleCallback (Handler.java:761)
  at android.os.Handler.dispatchMessage (Handler.java:98)
  at android.os.Looper.loop (Looper.java:156)
  at android.app.ActivityThread.main (ActivityThread.java:6623)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:942)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:832)

java.lang.NullPointerException: 
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.e (PurchaseManagerGoogleBilling.java:2)
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling.access$100 (PurchaseManagerGoogleBilling.java)
  or                     .dispose (PurchaseManagerGoogleBilling.java)
  or                     .purchase (PurchaseManagerGoogleBilling.java)
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling$1.run (PurchaseManagerGoogleBilling.java:27)
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling$2.a (PurchaseManagerGoogleBilling.java:40)
  at com.android.billingclient.api.BillingClientImpl$BillingServiceConnection.onServiceConnected (BillingClientImpl.java:228)
  at android.app.LoadedApk$ServiceDispatcher.doConnected (LoadedApk.java:1658)
  at android.app.LoadedApk$ServiceDispatcher$RunConnection.run (LoadedApk.java:1687)
  at android.os.Handler.handleCallback (Handler.java:789)
  at android.os.Handler.dispatchMessage (Handler.java:98)
  at android.os.Looper.loop (Looper.java:164)
  at android.app.ActivityThread.main (ActivityThread.java:6944)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.Zygote$MethodAndArgsCaller.run (Zygote.java:327)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1374)

java.lang.NullPointerException: 
  at com.badlogic.gdx.pay.android.googlebilling.PurchaseManagerGoogleBilling$3.onSkuDetailsResponse (PurchaseManagerGoogleBilling.java)
  at com.android.billingclient.api.BillingClientImpl$2$1.run (BillingClientImpl.java)
  at android.os.Handler.handleCallback (Handler.java:751)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:154)
  at android.app.ActivityThread.main (ActivityThread.java:6780)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1500)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1390)

java.lang.NullPointerException: 
  at com.prozhar.math.gdx_pay.PurchaseManagerGoogleBilling.access$300 (PurchaseManagerGoogleBilling.java)
  or                     .fetchOfferDetails (PurchaseManagerGoogleBilling.java)
  at com.prozhar.math.gdx_pay.PurchaseManagerGoogleBilling.access$100 (PurchaseManagerGoogleBilling.java)
  or                     .purchase (PurchaseManagerGoogleBilling.java)
  or                     .purchaseRestore (PurchaseManagerGoogleBilling.java)
  at com.prozhar.math.gdx_pay.PurchaseManagerGoogleBilling$1.run (PurchaseManagerGoogleBilling.java)
  at com.prozhar.math.gdx_pay.PurchaseManagerGoogleBilling$2.onBillingServiceDisconnected (PurchaseManagerGoogleBilling.java)
  or                     .onBillingSetupFinished (PurchaseManagerGoogleBilling.java)
  at com.android.billingclient.api.BillingClientImpl$BillingServiceConnection.onServiceConnected (BillingClientImpl.java)
  at android.app.LoadedApk$ServiceDispatcher.doConnected (LoadedApk.java:1208)
  at android.app.LoadedApk$ServiceDispatcher$RunConnection.run (LoadedApk.java:1225)
  at android.os.Handler.handleCallback (Handler.java:739)
  at android.os.Handler.dispatchMessage (Handler.java:95)
  at android.os.Looper.loop (Looper.java:135)
  at android.app.ActivityThread.main (ActivityThread.java:5268)
  at java.lang.reflect.Method.invoke (Method.java)
  at java.lang.reflect.Method.invoke (Method.java:372)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:902)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:697)

No, it is not the same error. It looks like you use the PurchaseManager after disposing.

Hi @MrStahlfelge I've been wanting to test your pull request but I've been getting an error with gradle.

I forked your repo and am trying to use Jitpack to include the sub repos.
Core:
implementation "com.github.alexdbooth:gdx-pay-client:issue~183-SNAPSHOT"
Android:
implementation "com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT"

Unable to resolve dependency for ':android@qa/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@qaUnitTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@rc/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@rcUnitTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@debug/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@debugAndroidTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@debugUnitTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@dev/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@devUnitTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@release/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Unable to resolve dependency for ':android@releaseUnitTest/compileClasspath': Could not resolve com.github.alexdbooth:gdx-pay-android-googlebilling:issue~183-SNAPSHOT.
Open File
Show Details


Failed to resolve: com.github.alexdbooth:gdx-pay-client:issue~183-SNAPSHOT
Open File
Show in Project Structure dialog

Haven't tried including libs this way before. What can I do here?

Hi, I can't help you how Jitpack handles things.

You can test by building the snapshot yourself: clone the repo on your machine and build the snapshot locally with gradlew clean uploadArchives -PLOCAL=true

Merged the fix, but snapshot is not updated. When this is done, this issue can be closed.

Fix is now published in 0.11.4-SNAPSHOT

Confirmed working on my end, thanks.