Android Expansion Files Error On First Load.

Hi Studycat;

Thanks so much for your suggestions!

Yes, we are clearing cache and uninstalling old builds (and restarting devices) before we try to go on to Google Play and test the new builds by downloading them.

Hmmm. I hadn’t thought of what you suggested for testing as I wasn’t certain that the APK (loaded locally via ADB) would know that it is coupled with the specific expansion file on Google Play that it needs to pull down. I though that “coupling” had to be done at the Google end. Am I incorrect on this?

And just to reiterate point from earlier in discussion, a full version of APK that doesn’t use an expansion file has no problem, EVER, when installed locally (or as a single APK by Nook store).

Thanks;

Steve

Hi Alex;

Thanks. But I do have a question . . .

One of my conclusions from my testing was that the “Corona Stub” (my name, see above) does ALL of its stuff before any line of my code in my main.lua is run. Was that assumption incorrect??

If my assumption is correct, then “display.newGroup()” has already been corrupted before a single line you have included above would be read/exectuted. And it wouldn’t do a thing to restore “display.newGroup()” to its normal functioning? WEhat am I missing here?

Steve

Hi Alex;

One very last clarification – after re-reading your post above (you seem to be thinking that I want to use widgets).

I don’t want to use widget.lua in my game and I never did (before this problem reared its delightful head). Using widgets is not my goal.

I want to cure a problem created by the “Corona Stub” (my definition, see above) when it uses widget.lua – before a single line of my code has run.

Steve

Hey sbullock,

Yes, i got it now (better later than never :)). I’ll be checking with dchan to see if we can do something for this case. Me or him will update the thread soon.

Thanks,

Alex

Thanks Alex!

And just to put in my 2 cents again . . . the best thing in the long run would be for the “Corona Stub” to clean up after itself and restore display.newGroup() before the “Stub” turns over control to the developer’s code :-). But that’s a fix that would have to take place in a build.

Hi sbullock,

I just tried it again and if I put a widget.lua file with just print(“asdfasdf”) in it then it prints that in the expansion file screen.  This leads me to believe that you did not set it up correctly.  Please make sure you put the widget.lua file in the sample directory as your main.lua file.

Hi dchan;

Hmmmmm. Just so I clearly understand:

You are building a test APK with an accompanying expansion file (". . .obb") and you are having the compiled pair launch on a device the way that it would after an installation on to a device from the Google Play store. Correct? Or are you doing this test a different way?

I ask because one of my builds on Google Play on Saturday (not the build up there now) had widget.lua next to main.lua and my print statement never fired (and the removeSelf errors were the same). I’m definitely willing to try it again in case there was something weird happening with cache or something – if you are confident that you are simulating the live sequencing and the way that the App gets built when there is an expansion file.

Note that Google makes me increment the build # with every new file pair uploaded (expansion file naming changes, etc.) – and I waited several hours until build information updated in Google Play each time I tried a new build on Saturday. But the matter of whether something cached may have messed things up is still a bit of an open question.

Thanks for all your work on this. Sure appreciate it.

Steve

What I do is that I upload to the Play Store with lets say version 2.  Then I keep building my app through the simulator as version 2.  I directly install the newly built app directly onto the device instead of uploading it to a playstore and waiting for them to refresh their cache.

Also please make sure you put your print statement at the top of widget.lua just so we’re sure that it reaches that code path.

I agree with your that our widget code should clean up after itself but that will take some time.  This is the best quick and dirty solution we have for you at the moment.

Thanks for the explanation of your methodology. That does make sense.

I will put the print statement at top (was putting it next to where I was changing the local to global).

I will place the widget.lua next to the main.lua.

It will be tomorrow morning when I try this (running out of “day” here on east coast). Will post my results to you when I know them. Fingers crossed.

Steve

We have just tried this and it works for us.

Perhaps I spoke to soon, testing on the device and looking at our logs there is some heavy recursion going on that doesn’t happen in the simulator. 

Example of what I am doing. It is probably not exactly the same as Steve’s error but I am sure it is related.

[lua]


– in the simulator this re-produces the error if we 

– override the display.newGroup function below


– require(“widget”) 


– using this modified widget file that makes cached_displayNewGroup()

– a global works in the simulator but not on device.


– require(“widgetLibrary.widget”) 

– function display.newGroup()

–     return cached_displayNewGroup()

– end

– Just for example, this override causes a recursive loop on first load

– on a device. We don’t use this anymore, as long as we don’t override 

– anything we’re fine. This override could be commented out and this 

– example will still run. fine.

local oldNewGroup = display.newGroup

display.newGroup = function( … )

    local group = oldNewGroup( … )

    local oldRemoveSelf = group.removeSelf

    

    group.removeSelf = function( self )

        if self.numChildren then

            for i = self.numChildren, 1, -1 do

                self[i]:removeSelf()

             end

         end

        

        oldRemoveSelf( self )

    end

    group.remove = function( self, o )

        if type( o ) == ‘number’ then

            self[o]:removeSelf()

        else

            print “group.remove removeSelf”

            o:removeSelf()

        end

    end

    return group

end

function cleanGroup( objectOrGroup )

    if objectOrGroup.numChildren then

        while objectOrGroup.numChildren > 0 do

            cleanGroup ( objectOrGroup[objectOrGroup.numChildren])

        end

    end

    

    print “clean group”

    objectOrGroup:removeSelf()

end

local testRoot = display.newGroup()

local testView = display.newGroup()

local testText = display.newText(“Adding new text to the testView display group”, 0, 0, native.systemFont, 9)

testText.x = 100

testText.y = 10

testView:insert(testText)

        

testRoot:insert(testView)

timer.performWithDelay(1000, function () cleanGroup(testRoot)  end)

[/lua]

Hi Studycat & dchan;

So sorry that I have been out of the loop for more than a day. Some important things came up on the personal side of life and I am away from work as a result. Plan to be back at it tomorrow to test further.

Steve

Steve 

No problem, I am just glad I am not the only one who has had this kind of problem.

Hi dchan, Studycat and Alex;

OK, I finally had the time to buckle down and test the things suggested. First off, dchan was correct with his suggestion of setting “cached_displayNewGroup” to a global. But spooky oddnesses surrounding “widget.lua” and how it does very interesting thing in different situations completely threw me and kept me a step away from properly implementing dchan’s suggested methodology when I tried it (nearly a week ago). I’m still not certain that I don’t have to do one last thing to make it all work in all instances – but I’ll get to that question a bit further down.

I have a bunch of observations on this and I will probably break this into separate posts – just so it all stays understandable.

WHAT ACTUALLY WORKS

  1. Place “widget.lua” in the main project directory next to “main.lua” and don’t worry that things are screwy if you ever try to actually instantiate it in the simulator (see below) in order to test in that environment.

  2. In the “widget.lua” file, change the “local” variable for cached_displayNewGroup to a global. Here’s my code and I include my print statements because stuff I will write in a bit will make more sense if you see them:

<snip>

local widget = 

{

    version = “2.0”,

    _directoryPath = “widgetLibrary.”,

}

print ("###########  WIDGET NEXT TO MAIN         TRACE POS #1")

– STEVE MODIFIED THIS IN ORDER TO RE-ESTABLISH THIS FUNCTION AFTER THE WIDGET SCRIPT HAS MESSED IT UP

– This cached_displayNewGroup was a “local”, but Steve made it a global

cached_displayNewGroup = display.newGroup

print ("###########  WIDGET NEXT TO MAIN         cached_displayNewGroup set to global")

print ("###########  WIDGET NEXT TO MAIN         TRACE POS #2")

function display.newGroup()

    local newGroup = cached_displayNewGroup()

<snip>

  1. Place the secondary widget files and the folder “widgetLibrary” (and contents) in the project as well. As I have no idea which of these files might be called or used (by Corona’s code) if the Google Play Expansion file still needs to be loaded, I placed them all there.

  2. Make certain that the “widgetLibrary” does not still contain a “widget.lua” file – this file should only exist on the same level as “main.lua”.

====== CONTINUED BELOW ========================================================================

WHY I HAD THOUGHT THIS DIDN’T WORK (previously)

Remember my comment at the beginning of the week that my print statements weren’t outputting with logcat?

I had actually tried two things to test the globalizing of cached_displayNewGroup and both failed in my test/

FIRST THING TRIED

THIS FAILS IN THE SIMULATOR:

  1. Place “widget.lua” in the main project directory next to “main.lua” with the variable set to be global.

  2. Place this code in “main.lua” to test it all in the simulator:

widget = require(“widget”)

if (cached_displayNewGroup) then

    print ("###########  MAIN (widget.lua next to main) - cached_displayNewGroup is NOT nil")

    function display.newGroup()

        return cached_displayNewGroup()

    end

else

    print ("###########  MAIN (widget.lua next to main) - cached_displayNewGroup IS NIL")

end

  1. When I run this, NONE of the print statements in “widget.lua” (see previous post) actually display (as widget is birthed) and cached_displayNewGroup is nil when I test for it.

  2. But, on the other hand, I know that the code in “widget.lua” actually did run (or the Widget code ran somewhere else) – it managed to hose the removeSelf() functionality of any dispely groups I tried to subsequently remove.

  3. After this essentially failed in the simulator, I didn’t think to try it fully on a build for the device (I should have)

=============================================================================

And another bit of simulator “voodoo”. If I change the name of the lua file

to “widget1.lua” and instantiate with this:

widget = require(“widget1”)

Then everything runs just fine with all print statements firing and 

cached_displayNewGroup is NOT nil!

I think I know what you are doing here, I just think it is strange that you

don’t document it anywhere. It will waste someone else’s hours down the road.

=============================================================================

====== CONTINUED BELOW ========================================================================

SECOND THING TRIED

Since I had that strange experience on the simulator, I decided to try everything by using a “widget.lua” file in the “widgetLibrary” folder (the default placement in your examples). When I simply did this and changed my widget=t birth to this:

widget = require(“widgetLibrary.widget”)

The result was that everything tested out well in the simulator and on a device (no expansion file yet, just a single APK). With these results under my belt, I optimistically made a Google Play Build and placed it in the store (with expansion file). Of course I commented out my own birthing of “widget” – I expected that the “Corona Stub” would do that.

I don’t know why I was optimistic. My print statements never fired and, apparently, the Corona Stub didn’t use my instance of “widget.lua” in the directory. So that is where I ended up earlier this week.

BUT THERE’S MORE INTERESTING STUFF (below)

====== CONTINUED BELOW ========================================================================

INTERESTING STUFF 

Did you know . . . .

**  That if you place a “widget.lua” file next to the “main.lua” file and you also place another copy of the “widget.lua” file in a “widgetLibrary” folder, BOTH FILES will be fired by the “Corona Stub” that handles the expansion file checking. The trace statements in each of them will run (file next to “main.lua” runs first). But after they each run, the app stops at a full black screen and nothing else happens (and there are no errors or anything outputted to explain the problem). What is fascinating here is that the “widget.lua” file in a “widgetLibrary” folder DOES NOT RUN when it is there all by itself (without a twin next to “main.lua”).

FINAL IMPORTANT CONCERN

The one thing that concerns me in the approach that I “think” is successful is that I get the following output on first run of the App after it is now downloaded from the Google Play Store. It is this:

> Class.forName: widgetLibrary.widget.luaLoader

WARNING: Could not load ‘LuaLoader’

> Class.forName: widgetLibrary.widget.luaLoader

WARNING: Could not load ‘LuaLoader’

What scares me here is whether this means that “if the APK portion of the app actually needed to go and download the “.obb” expansion file”, that things would break. I just don’t know and would love advice on what is triggering this and whether there is another LUA file I need to place in my project. I would appreciate advice.

Thanks;

Steve

Steve 

It’ll take me a while to read through all that slowly and see if it matches what I see.

Would you be able to make a concise example app? What I did was made an example app

by cut 'n pasting bits from our real app until I found what wasn’t working. If you had an example bit of code I’d be happy to run it here and see if I can get the same results as you.  It would also be easier for the Corona guys if they had something that reproduced the results and they could debug better.

Hi Studycat;

Thanks for the question. And thanks so much for your thoughts on approaches to the problem. I’m presently under the gun to complete a Flash game that I promised would be complete by late this week (yes, my web development roots are on the dark side and we still make money on this Flash stuff). So I’m not certain when I can get to it.

If you are simply interested in what worked for us, it is described in the 4 points of my first post on 8/23.

And if anyone has any questions about “why does this happen?”, it stems from the fact that the core widget code creates a replacement global display.newGroup() function that contains an altered removeSelf(). This removeSelf() is incompatible with the normal functioning of display groups and removing them when cleaning up properly.

And in the specific instance of a “Corona Stub” (that deals with an expansion file), the actual instance of “widget” is destroyed by the stub before the developer’s “main.lua” is run – but the corrupting global display.newGroup() function is left in place by the stub.

In the short, short run, the kludgy steps above eliminate my immediate problem.

In the less short run, Corona could fix this “Corona Stub” problem by reverting display.newGroup() to its intended functioning at the time when the stub has finished its work and is about to set the widget instance to nil.

And by far the best, most elegant solution would be for someone at Corona to write a better memory cleanup chunk of code in “widget.lua”; a chunk of code that does not supplant normal, documented Corona functionality in certain instances – with those instances producing the errors that we developers have experienced.

Does that make sense?

Thanks again for everyone’s help!

Steve