Simon, i just love you
Hi everyone,
I’ve updated IAP Badger to version 8 - here are the details:
Google IAP changes:
- IAP Badger now works with the breaking Google Play IAP changes in the latest builds of Corona SDK
- This won’t require any changes to your code <— (this is the bit you’re looking for)
- IAP Badger will handle the asynchronous element of Google Play initialisation; if you make any calls to the library such as loadProducts, restore or consumeAllPurchases that need initialisation to be completed before they can run, then these will automatically be queued and executed when the device is ready.
- Calls to purchase will also be queued in the same way (to be on the safe side)
- When working on the simulator, and specifying “google” as the debugStore, IAP Badger will simulate a short delay between returning from the iap.init function and the store being ready to accept calls; if you call a function before the simulated delay is complete, IAP Badger will queue them as it would on a real device (to give you more accurate off-device testing).
Backwards compatibility
For those of you who are using an older build of Corona, but the latest version of the IAP Badger, the asynchronous handling of Google IAP will be a breaking change on Google Play devices.
But don’t worry. If you’re stuck on a specific build of Corona for some reason, a single code change will instruct IAP Badger to go back to the old way of handling Google IAP.
Just set usingOldGoogle to true (or any non-nil value) in the initialisation table you pass to the init function.
Consuming purchases
- I’ve added a consumeAllPurchases function - on Google Play, this will consume every product in the catalogue, re-opening every IAP to purchase again, regardless of whether those products are consumable or non-consumable
- This is for testing purposes only! For when you want to wipe a testing user’s slate clean.
- Be aware that consuming products is not instantaneous - there will be a minor delay between calling the function and the purchases becoming available.
- This function is ignored on every platform except Google Play.
- Again - please don’t use this in the wild. It erases records of user purchases and it won’t make them happy.
Query the library version
- To help work around my (ahem) difficulties uploading the latest versions of the plug-in code, I’ve added a getVersion function call.
- This will return the version number of IAP Badger you are building with - the latest version is 8.
Better simulation
- I’ve improved how loadProducts (and its associated functions) work on the simulator, so they more accurately portray the kinds of delays your code will experience in real life.
Updated documentation
- I’ve spent a little time tidying up and adding some documentation for features that I’ve added but never really explained properly.
This has all been tested on a real device with the IAPs on one of my apps. I’ve uploaded the latest code to Github and Corona’s plug-in servers - and I’ve checked the plug-in. On my computer (in the UK) I’m definitely getting the latest version.
Any problems - let me know.
Enjoy
[EDIT]
PS - forgot to mention:
Debug function for Load Products
- IAP Badger now offers a debug function to support with the loadProducts process.
- Once loadProducts has finished downloading catalogue information from the relevant app store, you can use printLoadProductsCatalogue()function to print out that titles/descriptions/pricing etc to the console in human readable form (so you can check that the information you think you should receive is the same as the info you’re getting from the app store)
- printLoadProductsCatalogue will also let you know if the information hasn’t arrived yet, if there was an error etc.
Best support for a free plugin/downloadable module ever.
Thanks Roaming Gamer
Glad I found this thread because it explains some of the issues I’ve been having the last week or two with my updated app on the play store with nil being returned from getLoadProductsCatalogue(). Had never had this happen before on iOS or Android or on previous versions.
I’ve since updated to the latest Corona build and the latest IAP Badger but I’m still getting a nil response. Portion of code in main looks like the following:
local function loadProductsListener() \_G.products=iap.getLoadProductsCatalogue() end local function LoadProducts() \_G.iap.loadProducts(loadProductsListener) end
\_G.iap.init({catalogue = catalogue, filename = "abc.txt", salt = "xyz"}) timer.performWithDelay(50, LoadProducts)
_G.products is nil on Android as of recent builds, works fine for simulator and iOS and on Android prior to a week or so ago. Is there something else I’m missing? Has anyone else released an Android build in the last week or two with consumables and have this working?
Thanks
Roy
Hi there,
In your loadProductsListener function, could you please add the following line:
iap.printLoadProductsCatalogue()
You can include this anywhere in your listener function.
As well as printing the products catalogue, the printLoadProductsCatalogue function may also display some useful information about what’s happening (eg. it will let you know if an error has occurred, if IAP Badger is still waiting to hear back from the app store etc.)
Your loadProductsListener function will also receive, as its first parameter, the original Corona loadProducts event. That can contain some useful info, so I’d also print that out as well.
For example:
local function loadProductsListener(event) --Now print out event to the console to see if you're getting any more information from Corona end
Be aware that ‘event’ is a Corona table, so you won’t be able to just use the print function.
Let me know what the result is and hopefully we’ll get this fixed.
Kind regards,
Simon
Hi Simon,
I did what you suggested and here is what I found. First, the code now looks like:
local function loadProductsListener(event) print ("LoadProductsListener") \_G.products=iap.getLoadProductsCatalogue() iap.printLoadProductsCatalogue() end local function LoadProducts() print ("LoadProducts") \_G.iap.loadProducts(loadProductsListener) end print ("IAP Init") \_G.iap.init({catalogue = catalogue, filename = "temp.txt", salt = "Doesnt Matter"}) timer.performWithDelay(50, LoadProducts)
In the adb logcat, when running from the phone I get the “IAP Init” and the “Load Products” but the response never comes back so the listener never fires which explains why the products table is nil even when I check it minutes later in the purchase scene. Again this is only on the Android and only as of very recently.
In case timing matters, here is a timeline
* July 21 uploaded version 1.3 of my program using Corona 2016.4.x I believe - this version of my app works (or at least worked until at least the 28th, haven’t confirmed that it still works yet)
* July 28 uploaded versions 1.3.1 - this is when the problem started
I have since updated Corona to the latest release but problem persists
Let me know what else you would like me to try and thanks for the great support
Thanks,
Roy
Okay - so your app is never hearing back from Google Play.
The next step would be connect your device via USB and to fire up adb logcat - this will print additional IAP information and error messages that are coming from your app (some of these never get passed back to your code and get printed directly to the console instead).
I’d advise Googling a tutorial about using adb logcat with Corona, but the syntax is basically:
adb logcat Corona:v \*:s
Obviously, you’re only interested in the stuff about IAP, but this should give you more information about how to solve your issue.
Simon
PS - should have mentioned your connect your device, start adb logcat and then attempt to make a purchase on your device.
Hi Simon,
I do have adb logcat running and my last test was on the phone connected to my USB and I use that “adb logcat Corona:v *:s” to view the messages. I see all the messages my app is sending (using print statements) but there is nothing iap related after calling LoadProducts
The log is looks like:
IAP Init (from my code)
> Class.forName: plugin.google.iap.v3.LuaLoader
< Class.forName: plugin.google.iap.v3.LuaLoader
Loading via reflection: plugin.google.iap.v3.LuaLoader
Load Products (from my code)
then nothing else. Is there a debug mode I need to enter for IAP to enable verbose logging? Just to mention again, on simulator and iOS (and Android for the past 10 months or so up until this past week) it is working and LoadProducts calls the listener as expected.
Regarding making a purchase, I only show my IAP products if they are in the Product List and since the Product list is nil there are no IAP’s available so making a purchase isn’t possible, at least based on how its coded at the moment
Thanks
Roy
Leave the " Corona:v *:s" off. It will generate a lot of noise, but it’s the only way to see all intents and IAP runs in a different intent.
Rob
ok tried that, my phone seems to generate a couple hundred lines a second but after a bunch of attempts was able to get a good chunk following the “LoadProducts” print statement. It’s as if iap.loadProducts is not even running because I can’t see any logging that I would expect… Again, this is on Android only and only as of the last week or so
removed full adblogcat log because it is not relevant to problem
Also, was able to grab a previous apk released July 21st and when I copied that on to my phone, LoadProducts is working returning a product list and my store IAP entries are shown. My next update was July 28th and that build and all since then have this problem with Android (and Android only) where LoadProducts does not do anything
Roy
I’ve added a new command to the plug-in that will print out very detailed debug info that will help (hopefully).
To access it, add verboseDebugOutput=true to the table you pass to iap.init - then connect up your device to USB and see what the output is.
local iapOptions = { --Your product catalogue... catalogue=catalogue, --And whatever other options you already have... --Tell IAP Badger to print out debug info verboseDebugOutput=true, } iap.init(iapOptions)
For loadProducts, purchase and restore this prints out exactly what IAP Badger is doing every step of the way.
I’ve just uploaded the new plug-in, which will have version number 9. It should hit a server near you soon.
Simon
What version of Corona are you using? (please use the build number in the format YYYY.nnnn and not the YYYY.mm.dd format)
Are you trying to load products in main.lua immediately after calling the initialization function or are you calling it later?
Thanks
Rob
Rob, corona version is 2017.3068 and load products is being called in main a short time after init. It was set to 50 ms (which again has always worked for iOS and worked for Android up until a week ago), I tried switching it to a 2 second delay in my last test from the log below but no change. UPDATE: Just tried with a 20 second delay and still the same problem with the same logging.
Simon, here is the new log. At the bottom there is a “Google Play not yet initialised. Queuing loadProducts” entry. As far as I can tell the queued loadProducts never runs (I let the app run for 15 minutes and the listener was never called) but Google Play probably never gets initialised - again, going back to a build from a week earlier works and nothing notable changed besides the new IAP Badger release dealing with the Google Play and Corona SDK Google Play changes.
Roy
08-06 09:29:14.698 26741 26783 I Corona : IAP Init 08-06 09:29:14.698 26741 26783 I Corona : -------------------------------------------------------------------- 08-06 09:29:14.698 26741 26783 I Corona : IAP Badger: init 08-06 09:29:14.698 26741 26783 I Corona : Called with: 08-06 09:29:14.698 26741 26783 I Corona : table: 0xd3448760 { 08-06 09:29:14.698 26741 26783 I Corona : [verboseDebugOutput] =\> true 08-06 09:29:14.698 26741 26783 I Corona : [salt] =\> "Doesnt Matter" 08-06 09:29:14.698 26741 26783 I Corona : [filename] =\> "temp.txt" 08-06 09:29:14.698 26741 26783 I Corona : [catalogue] =\> table: 0xd3448760 { 08-06 09:29:14.699 26741 26783 I Corona : [inventoryItems] =\> table: 0xd34482e0 { 08-06 09:29:14.699 26741 26783 I Corona : } 08-06 09:29:14.699 26741 26783 I Corona : [products] =\> table: 0xd34482e0 { 08-06 09:29:14.699 26741 26783 I Corona : [buy20instantRecoveries] =\> table: 0xd3448340 { 08-06 09:29:14.699 26741 26783 I Corona : [onPurchase] =\> function: 0xd1d396a0 08-06 09:29:14.699 26741 26783 I Corona : [productNames] =\> table: 0xd3448600 { 08-06 09:29:14.699 26741 26783 I Corona : [apple] =\> "com.ultimatewrestling.myapp.20instantrecoveries" 08-06 09:29:14.699 26741 26783 I Corona : [amazon] =\> "com.ultimatewrestling.myapp.20instantrecoveries" 08-06 09:29:14.699 26741 26783 I Corona : [google] =\> "com.ultimatewrestling.myapp.20instantrecoveries" 08-06 09:29:14.699 26741 26783 I Corona : } 08-06 09:29:14.699 26741 26783 I Corona : [productType] =\> "consumable" 08-06 09:29:14.699 26741 26783 I Corona : } 08-06 09:29:14.699 26741 26783 I Corona : [buy50000credits] =\> table: 0xd3448340 { 08-06 09:29:14.699 26741 26783 I Corona : [onPurchase] =\> function: 0xd1d396a0 08-06 09:29:14.699 26741 26783 I Corona : [productNames] =\> table: 0xd34483e0 { 08-06 09:29:14.699 26741 26783 I Corona : [apple] =\> "com.ultimatewrestling.myapp.50000credits" 08-06 09:29:14.699 26741 26783 I Corona : [amazon] =\> "com.ultimatewrestling.myapp.50000credits" 08-06 09:29:14.699 26741 26783 I Corona : [google] =\> "com.ultimatewrestling.myapp.50000credits" 08-06 09:29:14.699 26741 26783 I Corona : } 08-06 09:29:14.699 26741 26783 I Corona : [productType] =\> "consumable" 08-06 09:29:14.699 26741 26783 I Corona : } \>\>\> A bunch of other products removed to make log smaller 08-06 09:29:14.704 26741 26783 I Corona : } 08-06 09:29:14.704 26741 26783 I Corona : } 08-06 09:29:14.704 26741 26783 I Corona : } 08-06 09:29:14.704 26741 26783 I Corona : 08-06 09:29:14.704 26741 26783 I Corona : 08-06 09:29:14.704 26741 26783 I Corona : VerboseDebugOutput set to true 08-06 09:29:14.705 26741 26783 I Corona : Running on Android (Google Play) 08-06 09:29:14.705 26741 26783 V Corona : \> Class.forName: plugin.google.iap.v3.LuaLoader 08-06 09:29:14.705 26741 26783 V Corona : \< Class.forName: plugin.google.iap.v3.LuaLoader 08-06 09:29:14.705 26741 26783 V Corona : Loading via reflection: plugin.google.iap.v3.LuaLoader 08-06 09:29:14.722 26741 26783 I Corona : Using synchronous Google IAP integration 08-06 09:29:14.722 26741 26783 I Corona : Waiting for store to initialise, queuing future store functions. 08-06 09:29:14.722 26741 26783 I Corona : IAP Badger: leaving init 08-06 09:29:14.750 26741 26783 I Corona : System Memory: 658 kB 08-06 09:29:14.750 26741 26783 I Corona : Texture Memory: 5.075 MB 08-06 09:29:16.746 26741 26783 I Corona : LoadProducts 08-06 09:29:16.746 26741 26783 I Corona : IAP Badger: loadProducts 08-06 09:29:16.746 26741 26783 I Corona : Google Play not yet initialised. Queuing loadProducts. 08-06 09:29:16.746 26741 26783 I Corona : IAP Badger: leaving loadProducts
Okay - I can see what is happening here.
IAP Badger puts any calls to loadProducts on hold until it hears back that Google Play is successfully initialised - these would cause your app to fail. (This also applies to purchase and restore requests).
However, your app is never getting a message back to say that Google Play has been initialised. If it were, you would get a report from the storeTransactionCallback function that it had received a Google Play initialisation event, but that never comes.
I think the reason is you’re using a build of Corona (2017.3068) that uses an older way of interfacing with Google IAP v3. The latest version of IAP Badger is designed to work with builds later than (2017.3015 - oops -> meant 2017.3105) that have a slightly different interface.
The solution should be to set usingOldGoogle to true in the table you pass to iap.init
Simon
ok will try that right away but isn’t the version of Corona I’m using 2017.3068 newer than 2017.3015? The number is bigger and 3068 seems to be the latest release build
UPDATE: I think you must have meant 2017.3105 not .3015 from daily builds
Roy
usingOldGoogle = true fixed it! I realize you must have meant 2017.3105 from the daily builds so I’ll get updated to that version and make sure that removing usingOldGoogle still works
Thanks,
Roy
Grabbing a recent live build of Corona and removing useOldGoogle works, thanks for helping me through this. I assumed downloading the latest official release of Corona would be enough without having to grab a Daily Build.
Thanks,
Roy
In fact, following the above conversation…
Library update
Version 9:
- library now automatically checks Corona build version to see how to interact with Google IAP v3 (so no need to explicitly set usingOldGoogle flag unless you want to)
- added verboseDebugOutput flag to init function (set this to true to get loads of debugging info about your app).
I’ve uploaded this so it should be available any minute now. Will also update the Github version.
Simon