"Androidize" App for Google Acceptance.

In addition, you should review Google’s Developer Content Policy:

https://play.google.com/about/developer-content-policy/

and:
 

https://developer.android.com/develop/quality-guidelines/index.html

In particular, the use of the Back Button is covered in their Core guidelines.  Android apps submitted to Google Play go through both and automated check and a human check, tough I don’t know if back button behavior is one of the things they are looking for. They seem to be more focused on avoid content and security violations.

Rob

@Brent Sorrentino, @Rob Miracle
Could you show me how to do that? I do not know if it is a global function (main lua) or I have to add it to the beginning of all my composer scene.

It all depends on what you want to do.  Here is an example of code I’ve used. My basic rules are this:

  1. is an overlay showing? hide it.

  2. is the current scene not the menu? Go to the menu

  3. is the current scene the menu? Exit the app

Hopefully any native dialog would handle the back button for me.

– main.lua

local function onKeyEvent( event ) local keyName = event.keyName print("in main.lua key handler") myData.exiting = false if "back" == keyName and event.phase == "up" then if composer.getSceneName("overlay") then composer.hideOverlay() elseif "menu" == composer.getSceneName("current") then print("platform", system.getInfo("platform") ) if "android" == system.getInfo("platform") then myData.exiting = true native.requestExit() end else composer.removeScene( "menu" ) composer.gotoScene( "menu", { effect = "crossFade", time = 800 } ) end return true end return false end Runtime:addEventListener("key", onKeyEvent )

or something like that.

Rob

Back button behaviour is absolutely checked.  Your app must behave like a browser would on Android to get approved.  The back button should navigate out of overlays, message boxes, web views, etc and then (and only then) suspend the app.

@Rob Miracle

Thanks for your answer Rob. I’m still not passing information through the modules, the only thing that I share are the modules of the “Image Sheet”. My App is created using only Corona documents and their respective examples. In your example, I can’t understand where does “myData” come from.
I wanted to ask you if I can use the “eventKey” individually in each module?
That way I could give the “back” order that suits my UI for a better app experience. I also understand that the “listeners” that are tied to buttons do not need to be removed because Corona takes care of them by inserting them into the “SceneGroup”, but the “runtime listeners” should be removed by me. If it is possible to use the “eventKey” in each individual module, In what phase of the “composer” would be ideal to use it and how the “runtime” must be removed? I will be slowly adapting my App to share information between modules, but I still don’t feel sufficiently capable of doing it.

@dodi no you only have this once and place it in your main module or in main.lua.

It is a Runtime listener so it exists throughout your project

myData is a table that I require in my different modules so I can easily pass data. See: https://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

You put this code in main.lua only.  As @sgs said, it’s on the global Runtime object.

Then if you need scene specific data, you can use composer functions to get the scene object of the current scene and then you can access methods and attributes you’ve added to the scene object.

For instance if you have a timer in the game scene that you want to pause instead of doing:

local myTimer = timer.performWithDelay(...)

do

scene.myTimer = timer.performWithDelay(...)

Then from any other scene or from this back key handler you can fetch the scene object:

gameScene = composer.getScene("game") -- assuming your game scene is in game.lua timer.pause( gameScene.myTimer )

Rob

@Rob or @SGS or @Brent
your code works good thanks!
I have 2 problems
​Number One
My app flow is:
main ==> menu_spanishmenu_spanish contains 3 buttons to go 3 diferent scenes … menu_spanish have a button to go to menu_english with 3 other scenes, in english of course, and menu_english have a button to go to menu_spanish. Summarizing, I swap to menu_spanish and menu_english with 2 buttons but menu_spanish and menu_english are two differrent scenes with its _spanish and _english children scenes. The problem is if I am in menu_spanish => _spanish scenes, the code works fine but when I go to menu_english => _english scenes, and I hit the “hardware>back” in simulator, returns me to menu_spanish instead of menu_english.

Here is the code:

--in mail lua local function onKeyEvent( event ) local phase = event.phase local keyName = event.keyName if keyName == "back" and phase == "up" then if composer.getSceneName( "overlay" ) then composer.hideOverlay() elseif "scenes.es.menu\_es" == composer.getScene( "current" ) then print( "platform", system.getInfo( "platform" ) ) if "android" == system.getInfo( "platform" ) then native.requestExit() end else composer.removeScene( "scenes.es.menu\_es" ) composer.gotoScene( "scenes.es.menu\_es" ) end return true end return false end --add the key callback Runtime:addEventListener( "key", onKeyEvent )

Number Two
With the code I return satisfactorily to “menu_spanish” but if I click again on the “hardware>back” in the simulator I receive this error message instead of sending me to “new project / open project” screen of the Corona simulator.

animation1 is a simple sprite animaton in the menu_spanish and menu_english. It has an animation1Sequence in the scene:create. Both the animation1 sprite and the animaton1Sequence are forward declared. I play it in the scene:show => “will” phase and pause it in scene:hide => “did” phase.

Any help is welcome.

Well for the first problem, you probably should set a variable that you can keep track of the current language and then look at that variable  in the back button handler and pick the right menu scene to go to. You can use composer.setVariable()/composer.getVariable() as a convenient way to save state variables like this.

As for the other issue, I would look at line 409 is the menu scene and ask yourself how that could be nil when attempting to go to that scene or leave that scene.

Rob

@Rob  --or anyone who can help me

Thank you for your reply. You are an excellent person.

I’ve had more than 30 attempts and this is what I have:

local function onKeyEvent( event ) local phase = event.phase local keyName = event.keyName print( event.phase, event.keyName ) if keyName == "back" and phase == "up" then if composer.getSceneName( "overlay" ) then composer.hideOverlay( "crossFade", 400 ) return true --without this the app close on android back button press else if composer.getScene == "scenes.es.menu\_es" then native.requestExit() return true --without this the app close on android back button press else local lastScene = composer.returnTo --from the official Android-izing tutorial print( "previous scene", lastScene ) if lastScene then composer.gotoScene( lastScene ) return true --without this the app close on android back button press else native.requestExit() end end end end return false end --add the key callback Runtime:addEventListener( "key", onKeyEvent )

and in every scene in the scene:show ==> “will” phase

composer.returnTo = "scenes.es.menu\_es" --\_spanish scenes

or

composer.returnTo = "scenes.en.menu\_en" --\_english scenes

and everything works fine, but in the “scenes.es.menu_es” scene, which is supposed to close the app on android back button press, what it does is a “reload scene” and never a  native.requestExit.

​Corona Simulator ERROR

What I have in line 409 is

-- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then elseif ( phase == "did" ) then animation1:pause() --line 409 bannerads1:pause() end end

animation1 is a sprite with his respective sequence created in scene:create and forward declared.  I play the animation (only one loop, “loopCount = 1”) in the scene:show ==> “will” phase. Also in scene:destroy I nil the sequence, the image sheet reference and the animation1 sprite, just in case.

Its very difficult to me detect what I’m doing wrong cause I’m doing all the code as Corona documentation says.

Thank you for all your attention.

Instead of

if composer.getScene == "scenes.es.menu\_es" then

replace with

if composer.getSceneName("current") == "scenes.es.menu\_es" then

and personally I wouldn’t have a scene per language, just translate a single scene.

Couple of thoughts on the error. @sgs nailed the problem in the event key listener. The other error regarding the animation error, you could wrap the animation1:pause() call in an if statement in case it’s getting removed.

if animation1 then

    animation1:pause()

end

Also, why are you starting it in the “will” phase? Your scene isn’t on the screen yet and depending on how long your scene transition is, you’re going to be missing that much of the animation. Animation, be it physics, transitions, or sprites and even audio tracks that should be seen/heard should be delayed until the scene is on the screen in the “did” phase.

Rob

Hi all,

It is possible to detect in any way if a transition to a new scene is happening or not?

This is due, If I dispatch the back key event pressing the back button while the scene is in the transition, all stops, and go back but the old scene is black screen.

Any idea to detect if the scene is on screen or not?

something similar to

getScenePhase… or scene.show = true…

Any one knows ?

Thanks all

You could accomplish this by detecting the phase of either the previous scene, or the destination scene, and setting a variable (if necessary) which could be used in your back key handler or whatever you need to do. In the previous scene, the “scene:hide()” --> “did” phase will indicate it’s fully offscreen. In the destination scene, the “scene:show()” --> “did” phase will indicate it’s fully onscreen.

Hope this helps,

Brent

Dear Brent,

Fantastic !!. Thanks for your excellent idea.

I’m using the follow:

local v = {} function scene:backKey() if v.onScreen then composer.gotoScene("sceneToReturn", {effect = "slideRight", time = 400}  ) return true end end

and… at the same scene, 

function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen and is about to move on screen elseif phase == "did" then -- Called when the scene is now on screen composer.removeHidden() v.onScreen = true -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end

so, as you teached me, when the scene is onScreen, the v.onScreen variable turn true… and the back key event can be handled…

and in the main.lua I have the following function:

local function onKeyEvent( event ) -- If the "back" key was pressed, then prevent it from backing out of the app. -- We do this by returning true, telling the operating system that we are overriding the key. if (event.keyName == "back") then local currScene = composer.getSceneName( "current" ) local objScene = composer.getScene (currScene) if ( objScene.backKey and type(objScene.backKey) == "function" ) then objScene:backKey() --call the function on the current scene return true end end --Return false to indicate that this app is \*not\* overriding the received key. --This lets the operating system execute its default handling of this key. --return false return true --return true to not finalize the app. end end if mG.platform ~= "IOS" and system.hasEventSource( "key" ) then -- Add the key callback Runtime:addEventListener( "key", onKeyEvent ); end

Thanks so much dear,

Yes, that looks basically good. I would, however, “reset” the “v.onScreen” variable to false during the “hide --> did” phase… just to ensure it’s always being set to what you intend.

Brent

I want to thank @Rob, @Brent and @SGS for all the help provided. I was able to code the “Android back button” the way I want.

@SGS
I am learning step by step. I already have in mind to make a function to change the texts and the images in the corresponding languages ​​instead of using the scenes. Thanks again!

@Rob
I do not know what happened. With the new Android back key function code, the animation error was solved. I’m using the “play / pause” in different phases proving which one fits the animation the way I want. Thanks again.

Growing up takes time.