Android Expansion Files Error On First Load.

Thanks dchan.

I’ll let you know what happens. Also, I’m assuming that my removing the override on display.newGroup won’t bust/break the ability of the app to diplay the widgets if it does need to complete the download of the expansion file. Appreciate your guidance.

Steve

What I think you should actually do is to modify 

https://github.com/coronalabs/framework-widgets/blob/master/widgetLibrary/widget.lua#L44

and remove the local keyword from that line.  Once you remove that it will become a global variable.  Once your main starts you can then do something like 

function display.newGroup()

    return cached_displayNewGroup()

end

which should restore display.newGroup() to its old functionality.  This way if the expansion files do need to be downloaded, the widgets are unmodified.  Its only when you get to your main.lua, which means expansion files are downloaded, that you break widgets.

Hi dchan;

Thanks. I spent my Saturday working on this. The result was utter failure.

For purposes of this discussion, I’ll call the Corona code which does all of the handling of the expansion file (linking of APK to Expansion, downloading of Expansion, etc.) the “Corona Stub”. After testing various things locally and then posting a pair of builds to Google Play, this is my analysis:

a) The “Corona Stub” runs before anything in my “main.lua” runs (had thought this would be the case).

b) During the build process, the “Corona Stub” probably loads its own version of widget.lua without regard to whether the developer is using (and loading) a widget.lua file of his own. As you described, the “Stub” may need to take over the downloading of the expansion file – so it always instantiates its own widget.lua the very first time an app is run.

c) Any widget.lua file placed in my own project files is entirely ignored and not used by the “Stub”. So making any changes within my widget.lua code has no impact on the problem. Any print statements in MY widget.lua file are never triggered. The change of the local “cached_displayNewGroup” to a global doesn’t happen – so I cannot reverse it.

d) Hence, the impact of a problematic piece of code written in widget.lua (where a core display function was hijacked so that it breaks the removeSelf() best recommended memory practice) has now created a problem in another piece of Corona functionality – the competent handling of expansion files.

e) In essence, I cannot restore display.newGroup() to its intended original and documented functionality. But you Corona folks could . . . if the “stub” code had about 5 lines of proper cleanup code of its own running.  The “stub” would do the cleanup once it knows that it has no more work to do. At that point, it could easily restore display.newGroup() and then it could set the entire “widget” to nil. This would effectively give developers back the “clean start” that they expect to have when their first line of “main.lua” runs.

So, I am totally open to thoughts and anything that will actually work. I do feel strong urgency on this. The game of ours that has the problem is “Just 2 Words” – your company’s choice as _ Corona App of the Month _ for July. The App has had about 150,000 downloads in last month on iOS – but only 1,500 in Google Play. It was an Apple New & Notable which really pushed its numbers on Apple. We have some advertising and promotion on the Android side this month – and we are handling e-mails daily asking “what gives, the game won’t run the first time.”

So far, we haven’t had a bunch of bomb reviews on this problem – but you never know when this might happen. As expansion files are a Google Play thing, this is not a hindrance to the App becoming a long running hit everywhere else. But it is certainly going to appear to be lame/broken if acquired through Google Play - until we can figure something out.

Thanks!

Steve

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]