Android Expansion Files Error On First Load.

Hi sbullock,

You have to include the widgets from the local directory in order for the local copy to take precedence over the widget library that comes with Corona. After downloading the widget framework from GitHub and placing it into your project’s folder, look at this sample:

https://github.com/coronalabs/framework-widgets-sample

It illustrates how to include the widgets so they are used from the local copy.

If you need any further help, don’t hesitate to ask.

Thanks,

Alex
 

Steve

Just to let you know you are not the only one who has spent a lot of time stuck on this and your comments pretty much match everything we’ve experienced.

I just have one question, if you clear your applications cache does that cause the problem to re-appear?

That leads me on to the only, not very good, suggestion I have:

We did get a release out without this problem by trying different daily builds (and removing our overrides of the sdk functions!)

It’s not a real solution but if you want to get a version up that doesn’t have this expansion file problem we had to try a few different builds before we got one that worked. (shortly after expansion file support was added, so it was some time ago!)  

To more rapidly test against different builds you can try this. 

Install app to device from the play store initially.

Use “adb install -r <name>.apk”   to re-install the app built with a different corona daily build

On the device clear cache and clear data.

Launch application and see if it loads first time.

I was using build 1168 for quite a while, but could have been as far back as 1137.

I think you would want to try more recent builds. Reading the change log I see things could have changed 

It’s getting late where I am but I’ll upload a new apk with a recent build double check your results above.

Also I would follow corona’s suggestions over our’s!

We will also be trying their suggestions ASAP.

Hi Alex;

Thanks for chiming in.

What you suggest is exactly what I spent my Saturday doing. And I tried two different builds in Google Play (with our App) – one where the “widget.lua” file was left in its default directory of “widgetLibrary” (as you set it up) and another where I promoted it to the same level as my “main.lua”. In both cases, I placed a PRINT statement in my copy of “widget.lua” to see if it was actually used by the “Stub”. And my file wasn’t used by the stub. So, in both cases, there was no way that following dchan’s suggestion had any salutary effect on the problem.

Note also that I placed ALL of the widget files (including themes and everything) in my project because the code in the “Stub” is hidden (from me) – I didn’t want it to break when it couldn’t find something.

Best;

Steve

Ok, what about:

-- Nil out the preloaded theme files so we load the local ones package.preload.widget\_theme\_ios = nil package.preload.widget\_theme\_ios\_sheet = nil package.preload.widget\_theme\_android = nil package.preload.widget\_theme\_android\_sheet = nil -- Override Corona's core widget libraries with the files contained in this project's subdirectory. -- Argument "name" will be set to the name of the library being loaded by the require() function. local function onRequireWidgetLibrary(name) return require("widgetLibrary." .. name) end package.preload.widget = onRequireWidgetLibrary package.preload.widget\_button = onRequireWidgetLibrary package.preload.widget\_momentumScrolling = onRequireWidgetLibrary package.preload.widget\_pickerWheel = onRequireWidgetLibrary package.preload.widget\_progressView = onRequireWidgetLibrary package.preload.widget\_scrollview = onRequireWidgetLibrary package.preload.widget\_searchField = onRequireWidgetLibrary package.preload.widget\_segmentedControl = onRequireWidgetLibrary package.preload.widget\_spinner = onRequireWidgetLibrary package.preload.widget\_slider = onRequireWidgetLibrary package.preload.widget\_stepper = onRequireWidgetLibrary package.preload.widget\_switch = onRequireWidgetLibrary package.preload.widget\_tabbar = onRequireWidgetLibrary package.preload.widget\_tableview = onRequireWidgetLibrary

given that the widget.lua is in the directory “widgetLibrary”, you would be able to include widgets like:

local widget = require( "widget" )

And that would definitely use the local copy.

Alex

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 ========================================================================