Google Play IAP crash when restoring purchases

store.restore() crashes my app on Android

In logcat I see:

10-14 15:17:40.401: E/IABUtil/Security(15432): Purchase verification failed: missing data.

10-14 15:17:40.401: W/IabHelper(15432): In-app billing warning: Purchase signature verification **FAILED**. Not adding item.

10-14 15:17:40.401: W/dalvikvm(15432): threadid=15: thread exiting with uncaught exception (group=0x40ab2228)

10-14 15:17:40.411: E/EmbeddedLogger(249): App crashed! Process: com.testapp.testapp

10-14 15:17:40.411: E/AndroidRuntime(15432): FATAL EXCEPTION: Thread-1609

10-14 15:17:40.411: E/AndroidRuntime(15432): java.lang.NullPointerException

10-14 15:17:40.411: E/AndroidRuntime(15432): at plugin.google.iap.v3.LuaLoader$3.onQueryInventoryFinished(LuaLoader.java:238)

10-14 15:17:40.411: E/AndroidRuntime(15432): at plugin.google.iap.v3.util.IabHelper$2.run(IabHelper.java:633)

10-14 15:17:40.411: E/AndroidRuntime(15432): at java.lang.Thread.run(Thread.java:864)

10-14 15:17:40.421: E/EmbeddedLogger(249): App crashed! Package: com.testapp.testapp v2 (0.51)

10-14 15:17:40.421: E/EmbeddedLogger(249): App crashed! Application Label: App name

10-14 15:17:40.421: W/ActivityManager(249):   Force finishing activity com.testapp.testappg/com.ansca.corona.CoronaActivity

Doesn’t output any errors in the adb logcat Corona:v *:s

Ideas?

Hi @info806,

Are you using IAP v3 or the “original” version?

Brent

thanks for the quick reply.  v3 I believe.

in my build.settings:

plugins =

{

   [“plugin.google.iap.v3”] =

   {

publisherId = “com.coronalabs”,

supportedPlatforms = { android=true }

   },

}

Also I don’t remember for sure but seems like this issue started happening after I did a test purchase with store.purchase( “android.test.purchased” )

Can you please post your code showing your transaction listener function and any other relevant code?

Thanks,

Brent

P.S. - I changed your user name to “Russpuppy” again. Not sure how it was reverted, but it should stick now.

Thanks for the name change

Here’s some of my code:

if(_LOCKED)then

    if ( system.getInfo( “platformName” ) == “Android” ) then

            store = require( “plugin.google.iap.v3” )

            v3 = true

    elseif ( system.getInfo( “platformName” ) == “iPhone OS” ) then

            store = require( “store” )

    else

            --native.showAlert( “Notice”, “In-app purchases are not supported in the Corona Simulator.”, { “OK” } )

    end

    

    function transactionCallback( event )

            local transaction = event.transaction

            local tstate = event.transaction.state

            

            --Google does not return a “restored” state when you call store.restore()

            --You’re only going to get “purchased” with Google. This is a work around

            --to the problem.

            –

            --The assumption here is that any real purchase should happen reasonably

            --quick while restores will have a transaction date sometime in the past.

            --5 minutes seems sufficient to separate a purchase from a restore.

            –

            if  (system.getInfo( “platformName” ) == “Android” and tstate == “purchased”) then

               local timeStamp = utility.makeTimeStamp(transaction.date,“ctime”)

               if timeStamp + 360 < os.time() then  – if the time stamp is older than 5 minutes, we will assume a restore.

                  tstate = “restored”

                  restoring = false

               end

            end

            

            if tstate == “purchased” then

                    native.showAlert( “Purchase success”, “Purchase complete, app now unlocked”, { “OK” } )

                    mySettings.isPaid = true

                    utility.saveTable(mySettings, “settings.json”)

            elseif  tstate == “restored” then

                    native.showAlert( “Purchase restored”, “Purchase restored, app now unlocked”, { “OK” } )

                    mySettings.isPaid = true

                    utility.saveTable(mySettings, “settings.json”)

            elseif tstate == “cancelled” then

                    native.showAlert( “Purchase was cancelled”, “App remains locked”, { “OK” } )

            elseif tstate == “failed” then

                    print(“Transaction failed, type:”, transaction.errorType, transaction.errorString)

                    native.showAlert( "Error: "…transaction.errorType, transaction.errorString, { “OK” } )

            else

                    print(“unknown event”)

            end 

            store.finishTransaction( transaction )

    end

    if ( system.getInfo( “platformName” ) == “iPhone OS” ) then

            store.init( “apple”, transactionCallback)

    end

    if ( system.getInfo( “platformName” ) == “Android” ) then

            store.init( “google”, transactionCallback )

            – doing a store.restore() here freezes the app

    end

end



– later in the app in some button listeners I call 

store.purchase( “android.test.purchased” ) --test

– and

store.restore() --results in app crash no matter if it’s at app start or in button listener

just in case this helps here is my config.lua:

application = {

content = {

width = 320,

height = 480, 

scale = “letterbox”,

fps = 60

–[[

        imageSuffix = {

   ["@2x"] = 2,

}

–]]

},

 

 

license =

{

   google =

   {

key = “my license key is here”,

   },

},

    

launchPad = false,

}

and my build.settings:

settings = {

 

orientation = {

default = “landscapeRight”,

supported = { “landscapeRight”, }

},

 

iphone = {

plist = {

UIStatusBarHidden = false,

UIPrerenderedIcon = true, – set to false for “shine” overlay

–UIApplicationExitsOnSuspend = true, – uncomment to quit app on suspend

 

            --[[

            – iOS app URL schemes:

            CFBundleURLTypes =

            {

                {

                    CFBundleURLSchemes =

                    {

                        “fbXXXXXXXXXXXXXX”, – example scheme for facebook

                        “coronasdkapp”, – example second scheme

                    }

                }

            }

            --]]

}

},

 

android =

{

   usesPermissions =

   {

“android.permission.INTERNET”,

“com.android.vending.BILLING”,

“com.android.vending.CHECK_LICENSE”,

   }

},

 

plugins =

{

   [“plugin.google.iap.v3”] =

   {

publisherId = “com.coronalabs”,

supportedPlatforms = { android=true }

   },

}

}

 

thanks!

I reset my phone and set it up with a new account that hasn’t yet purchased anything (I had purchased with store.purchase( “android.test.purchased” ) with my other test account), and it doesn’t give me the issue when using restore() before making any purchases.  However I just set this up as a test account so it will probably take an hour or two for Google Play to register this user as a test user for this app, so not sure how that affects things. 

I will attempt to try with a an actual app purchase ID instead of using the android test purchase id (android.test.purchased) that I used before and see if that makes a difference, seems like maybe the test purchase is messing things up with my test account.

I’ll report back on what I find…

Russpuppy, I kind of remember getting a strange crash with Google Play IAP with my latest app that’s been published to Alpha for testing.  But somehow, it fixed itself.  I wonder if you are experiencing the same thing.  

To be more specific, in my case, IAP simply failed when I tried to make any purchases or restore anything.  It was with my release build (that suppressed print statements.)  So, I generated a new APK that allowed the print statements (and I made no other changes), uploaded it to Google Play, waited a day (or two, maybe.)  When I got around to testing it, IAP worked perfectly fine.  So, I went ahead and generated another release build, uploaded, waited a couple days (because I was in no hurry anyway), and tested the IAP again, and it worked.  I do not know what the magic was.  

This may not be the case with you, but I thought I’d mention just in case.

Naomi

Thanks Naomi, yeah I think I’m going to try to get it as correct as I can and get my published beta APK to where I want it, then I’ll try again in the morning.

Ok, I think there was something funky with the fact that I used store.purchase( “android.test.purchased” ) on my first test account.  My new test account seems to working just fine, I’m able to make purchases and restore purchase and everything now.

Hi @info806,

Are you using IAP v3 or the “original” version?

Brent

thanks for the quick reply.  v3 I believe.

in my build.settings:

plugins =

{

   [“plugin.google.iap.v3”] =

   {

publisherId = “com.coronalabs”,

supportedPlatforms = { android=true }

   },

}

Also I don’t remember for sure but seems like this issue started happening after I did a test purchase with store.purchase( “android.test.purchased” )

Can you please post your code showing your transaction listener function and any other relevant code?

Thanks,

Brent

P.S. - I changed your user name to “Russpuppy” again. Not sure how it was reverted, but it should stick now.

Thanks for the name change

Here’s some of my code:

if(_LOCKED)then

    if ( system.getInfo( “platformName” ) == “Android” ) then

            store = require( “plugin.google.iap.v3” )

            v3 = true

    elseif ( system.getInfo( “platformName” ) == “iPhone OS” ) then

            store = require( “store” )

    else

            --native.showAlert( “Notice”, “In-app purchases are not supported in the Corona Simulator.”, { “OK” } )

    end

    

    function transactionCallback( event )

            local transaction = event.transaction

            local tstate = event.transaction.state

            

            --Google does not return a “restored” state when you call store.restore()

            --You’re only going to get “purchased” with Google. This is a work around

            --to the problem.

            –

            --The assumption here is that any real purchase should happen reasonably

            --quick while restores will have a transaction date sometime in the past.

            --5 minutes seems sufficient to separate a purchase from a restore.

            –

            if  (system.getInfo( “platformName” ) == “Android” and tstate == “purchased”) then

               local timeStamp = utility.makeTimeStamp(transaction.date,“ctime”)

               if timeStamp + 360 < os.time() then  – if the time stamp is older than 5 minutes, we will assume a restore.

                  tstate = “restored”

                  restoring = false

               end

            end

            

            if tstate == “purchased” then

                    native.showAlert( “Purchase success”, “Purchase complete, app now unlocked”, { “OK” } )

                    mySettings.isPaid = true

                    utility.saveTable(mySettings, “settings.json”)

            elseif  tstate == “restored” then

                    native.showAlert( “Purchase restored”, “Purchase restored, app now unlocked”, { “OK” } )

                    mySettings.isPaid = true

                    utility.saveTable(mySettings, “settings.json”)

            elseif tstate == “cancelled” then

                    native.showAlert( “Purchase was cancelled”, “App remains locked”, { “OK” } )

            elseif tstate == “failed” then

                    print(“Transaction failed, type:”, transaction.errorType, transaction.errorString)

                    native.showAlert( "Error: "…transaction.errorType, transaction.errorString, { “OK” } )

            else

                    print(“unknown event”)

            end 

            store.finishTransaction( transaction )

    end

    if ( system.getInfo( “platformName” ) == “iPhone OS” ) then

            store.init( “apple”, transactionCallback)

    end

    if ( system.getInfo( “platformName” ) == “Android” ) then

            store.init( “google”, transactionCallback )

            – doing a store.restore() here freezes the app

    end

end



– later in the app in some button listeners I call 

store.purchase( “android.test.purchased” ) --test

– and

store.restore() --results in app crash no matter if it’s at app start or in button listener

just in case this helps here is my config.lua:

application = {

content = {

width = 320,

height = 480, 

scale = “letterbox”,

fps = 60

–[[

        imageSuffix = {

   ["@2x"] = 2,

}

–]]

},

 

 

license =

{

   google =

   {

key = “my license key is here”,

   },

},

    

launchPad = false,

}

and my build.settings:

settings = {

 

orientation = {

default = “landscapeRight”,

supported = { “landscapeRight”, }

},

 

iphone = {

plist = {

UIStatusBarHidden = false,

UIPrerenderedIcon = true, – set to false for “shine” overlay

–UIApplicationExitsOnSuspend = true, – uncomment to quit app on suspend

 

            --[[

            – iOS app URL schemes:

            CFBundleURLTypes =

            {

                {

                    CFBundleURLSchemes =

                    {

                        “fbXXXXXXXXXXXXXX”, – example scheme for facebook

                        “coronasdkapp”, – example second scheme

                    }

                }

            }

            --]]

}

},

 

android =

{

   usesPermissions =

   {

“android.permission.INTERNET”,

“com.android.vending.BILLING”,

“com.android.vending.CHECK_LICENSE”,

   }

},

 

plugins =

{

   [“plugin.google.iap.v3”] =

   {

publisherId = “com.coronalabs”,

supportedPlatforms = { android=true }

   },

}

}

 

thanks!

I reset my phone and set it up with a new account that hasn’t yet purchased anything (I had purchased with store.purchase( “android.test.purchased” ) with my other test account), and it doesn’t give me the issue when using restore() before making any purchases.  However I just set this up as a test account so it will probably take an hour or two for Google Play to register this user as a test user for this app, so not sure how that affects things. 

I will attempt to try with a an actual app purchase ID instead of using the android test purchase id (android.test.purchased) that I used before and see if that makes a difference, seems like maybe the test purchase is messing things up with my test account.

I’ll report back on what I find…

Russpuppy, I kind of remember getting a strange crash with Google Play IAP with my latest app that’s been published to Alpha for testing.  But somehow, it fixed itself.  I wonder if you are experiencing the same thing.  

To be more specific, in my case, IAP simply failed when I tried to make any purchases or restore anything.  It was with my release build (that suppressed print statements.)  So, I generated a new APK that allowed the print statements (and I made no other changes), uploaded it to Google Play, waited a day (or two, maybe.)  When I got around to testing it, IAP worked perfectly fine.  So, I went ahead and generated another release build, uploaded, waited a couple days (because I was in no hurry anyway), and tested the IAP again, and it worked.  I do not know what the magic was.  

This may not be the case with you, but I thought I’d mention just in case.

Naomi

Thanks Naomi, yeah I think I’m going to try to get it as correct as I can and get my published beta APK to where I want it, then I’ll try again in the morning.

Ok, I think there was something funky with the fact that I used store.purchase( “android.test.purchased” ) on my first test account.  My new test account seems to working just fine, I’m able to make purchases and restore purchase and everything now.