Crashing on 1st Gen Kindle Fire

I’ve been getting reports that a new update made with Corona build 2830 is crashing on first generation Kindle Fire’s.  I only have a Fire HD to test and it works fine.  I was able to get this stack trace from Amazon.  It seems to happen at application launch.  Any ideas?

java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:365)
    at plugin.amazon.iap.LuaLoader$1.executeUsing(LuaLoader.java:241)
    at com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:148)
    at com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91)
    at com.ansca.corona.Controller.updateRuntimeState(Controller.java:300)
    at com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRenderer.onDrawFrame(CoronaGLSurfaceView.java:421)
    at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1623)
    at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1378)

java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:365)
    at plugin.amazon.iap.LuaLoader$1.executeUsing(LuaLoader.java:241)
    at com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:148)
    at com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91)
    at com.ansca.corona.Controller.updateRuntimeState(Controller.java:300)
    at com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRenderer.onDrawFrame(CoronaGLSurfaceView.java:421)
    at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1623)
    at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1378)

Do you have a URL for the app?

Rob

http://www.amazon.com/Barnyard-Games-for-Kids-Free/dp/B0076ANQQC

Thanks Rob!

I was hoping there would be more in the console log, unfortunately there isn’t. However, its coming from the Amazon IAP plugin. Now I can’t tell if you’re using the new Amazon plugin or the old one (II don’t think you should be able to get to the old one an longer). But you’re getting a null pointer.

Perhaps it would be helpful for you to share your build.settings and  your IAP setup code. It’s getting into displaying the main menu and getting some audio playing before it crashes.

Perhaps it’s trying to handle a transaction as the result of calling store.restore(). Adding some prints along your IAP calls might help narrow down when it’s occurring.

Rob

Thanks Rob, I’m using the new IAP code.  In fact this update was specifically to start using the new plugin.  What’s odd is it works fine in every single Kindle/Android device except for the first gen Fire.  Any clue why would that handle IAP’s differently?

I call store.restore as the very last thing on enterScene, so everything should already be setup at that point.

The only thing I can suggest is to put in some print statements. Perhaps the KF1 is giving a different result to a call back function.

Hey Rob, I’ve added a few catches for null pointers to some of my IAP code and also added a bunch of print debug statements.  Any chance I could send you an APK somehow that you could test on your first-gen Fire?  I’d really appreciate it!

Sure. You can put it on dropbox and give me (or anyone else in the forums with a First 1 KF) a chance to look at it.

Rob

Great, thank you!  APK is uploaded here:

https://www.dropbox.com/sh/b7a24chbparqtuz/AABesmSVscLPWQg3-4OFBPHPa?dl=0

Good news! … maybe… It did not crash!

There was an error when I tried to purchase that reads:

W/ActivityManager( 1415): Unable to start service Intent { act=com.amazon.testclient.iap.purchase flg=0x10000000 cmp=com.amazon.sdktestclient/.command.CommandBroker (has extras) }: not found

Since my KF isn’t setup for doing testing, it’s possible its not getting to whatever point was crashing you. I’ve installed the testing app, but I need your .json file to load on.

Rob

All of the users I’ve heard from are crashing on startup, not on purchase so it sounds like my checks for null worked!  I don’t have a JSON for testing made but I’m sure that piece is working fine.  For anyone else who is having issues, on my transactionCallback and loadProductsCallback I just added:

if event ~= nil then

It sounds like for some reason the first-gen Kindle Fire was passing a null event to the handlers.

Thanks a bunch for testing Rob!

I could have gotten past the crash part because it was unable to actually try and exercise the API. But if you’re confident with the fix, go for it.

Rob

Ohhhh I see what you mean.  You tested a production version earlier, and this is a test version.  I just uploaded the json file to that dropbox folder.

No errors with the testing environment. It showed me the price this time which it didn’t before.

Rob

Wonderful, thank you again Rob.  I’ll submit the update now and should be able to tell if it’s fixed within a day or two.

Well I’m still getting reports of crashes with the new version.  But whats odd is I’m seeing crashes on all types of Kindle now’s, not just first-gens.  I’m not able to replicate on my Kindle Fire HD, it loads and plays just fine.  Rob, can I ask another favor and when you have time, could you uninstall and download the current version on Amazon?  I’d really appreciate it!  Very odd behavior here.

http://www.amazon.com/Barnyard-Games-for-Kids-Free/dp/B0076ANQQC

version 3.2?

Yup.

It crashed after the menu of options showed up. This was what was in the console.

W/dalvikvm( 7808): threadid=8: thread exiting with uncaught exception (group=0x400155a8)
E/AndroidRuntime( 7808): FATAL EXCEPTION: GLThread 9
E/AndroidRuntime( 7808): java.lang.NullPointerException
E/AndroidRuntime( 7808):     at java.util.Hashtable.put(Hashtable.java:369)
E/AndroidRuntime( 7808):     at plugin.amazon.iap.LuaLoader$1.executeUsing(LuaLoader.java:241)
E/AndroidRuntime( 7808):     at com.ansca.corona.CoronaRuntimeTaskDispatcher$TaskEvent.Send(CoronaRuntimeTaskDispatcher.java:148)
E/AndroidRuntime( 7808):     at com.ansca.corona.events.EventManager.sendEvents(EventManager.java:91)
E/AndroidRuntime( 7808):     at com.ansca.corona.Controller.updateRuntimeState(Controller.java:300)
E/AndroidRuntime( 7808):     at com.ansca.corona.graphics.opengl.CoronaGLSurfaceView$CoronaRenderer.onDrawFrame(CoronaGLSurfaceView.java:421)
E/AndroidRuntime( 7808):     at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1623)
E/AndroidRuntime( 7808):     at com.ansca.corona.graphics.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1378)
W/ActivityManager( 1404):   Force finishing activity com.kevinbradford.games.barnyardgamesfree/com.ansca.corona.CoronaActivity

The plugin is still getting a null pointer exception. What activity is going on with the store at that point?

Put in some print statements around your store actions. In the transaction handler, put in the line:

print( json.prettify( event ) )

near the top of the function (you will have to require the json library as well). We need some intel on what values you’re passing to functions and what you’re getting back.

Rob

So same behavior as before when you download from the store.  It’s interesting that when you side loaded the APK it worked fine, but downloaded from the store breaks everything.  Sounds like I’d have to put back in print statements into the code and go through the Amazon process again in order to really debug it.

I have this at the end of my enterScene method, which must be causing all the problems.  Amazon wants us to call a store.restore to check if a new install had previously purchased, and I figure enterScene would be the best place to do it.

 -- attempt amazon restore if it's their first time loading if deviceBuild == "kindle" and fullVersion == false then if tonumber(fileHandler.getValue( "attemptedAmzRestore", 0 )) == 0 then -- do once --print("DEBUG: checking for amazon restore") fileHandler.setValue( "attemptedAmzRestore", 1 ) store.restore() end end 

Here’s the rest of my store code, it’s a bit disjointed but it has been working for years on Amazon/Apple/Google so I know it’s solid.

local store = require("store") if (system.getInfo("targetAppStore") == "amazon") or (deviceBuild == "kindle" and system.getInfo("environment") == "simulator") then store = require "plugin.amazon.iap" end

transactionCallback = function ( event ) if event ~= nil then if event.transaction ~= nil then --print("DEBUG: transaction callback") local transaction = event.transaction if transaction.state == "purchased" then --print("Transaction succuessful!") unlockAll() elseif transaction.state == "restored" then --print("DEBUG: transaction callback - restored") unlockAll() --print("Transaction restored (from previous session)") --print("productIdentifier", transaction.productIdentifier) --print("receipt", transaction.receipt) --print("transactionIdentifier", transaction.identifier) --print("date", transaction.date) --print("originalReceipt", transaction.originalReceipt) --print("originalTransactionIdentifier", transaction.originalIdentifier) --print("originalDate", transaction.originalDate) elseif transaction.state == "cancelled" then --print("User cancelled transaction") elseif transaction.state == "failed" then --print("Transaction failed, type:", transaction.errorType, transaction.errorString) else --print("unknown event") end -- Once we are done with a transaction, call this to tell the store -- we are done with the transaction. -- If you are providing downloadable content, wait to call this until -- after the download completes. store.finishTransaction( transaction ) --print("DEBUG: transaction finish") end end end

--print("DEBUG: store init") store.init( transactionCallback ) if (deviceBuild == "ios" or deviceBuild == "kindle") and ( store.canLoadProducts ) then --print("DEBUG: load products 1") store.loadProducts( listOfProducts, productCallback ) end 

local function productCallback( event ) print( "Showing valid products:", #event.products ) for i = 1,#event.products do print( event.products[i].title ) print( event.products[i].description ) print( event.products[i].price ) print( event.products[i].localizedPrice ) print( event.products[i].priceLocale ) print( event.products[i].productIdentifier ) price = "Price: " .. tostring(event.products[i].localizedPrice) end -- print( "Showing invalid products:", #event.invalidProducts ) -- for i = 1,#event.invalidProducts do -- print( event.invalidProducts[i] ) -- end end