Android Back button doesn't go back or crashes

To change scenes using the hardware back button for Android, I’m using this code:

local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects = nil director:changeScene("scene") end return returnValue end

And no matter what scene it’s in, it always goes to “Menu”.  The sequence in my app goes like this:

Menu -> Scene1 -> Scene2 -> Scene3

Scene1 goes back to Menu, Scene2 should go back to Scene1 and Scene3 shold go back to Scene2 … but Scene2 and 3 always go back to the Menu regardless of what "director:changeScene() is and regardless if the Runtime listener is removed. Maybe I’m not removing them properly, but I’ve tried almost every trick in the book. On some scenes, the app just crashes. I have the latest build. Can anyone help?

Hi Silky,

Is “Menu” in your code actually represented by “main.lua”?

In this line…

[lua]

director:changeScene(“scene”)

[/lua]

…what does “scene” represent? I can’t recall exactly how Director handles this, but “scene” should mean “scene.lua” as far as I know, and perhaps if that module doesn’t exist, it defaults to “main.lua”.

Brent

I put “scene” to represent the scenes which would be “scene1.lua”, etc. Here’s a tree of what I have, “<–” represents my back key behaviors.

main.lua --> menu.lua --> tutorialmenu.lua --> tutorial1.lua
                                    <--  tutorialmenu.lua
                                    <-----------------------------  tutorial1.lua      Goes back 2 scenes instead of the previous.

So instead of “tutorial1” going back to “tutorialmenu”, it goes all the way back to “menu”. And this goes for every tutorial module I have, “tutorialmenu” is the only one that goes back to the previous scene.

 

-- menu.lua local function toTutorials( event ) if event.phase == "ended" then display.remove(Objects);Objects=nil director:changeScene("tutorialmenu", "crossfade") end end tutBtn = widget.newButton { width = 429, height = 118, defaultFile = "tutBtn.png", overFile = "tutBtn-over.png", id = "tutBtn", onEvent = toTutorials, } tutBtn.x = display.contentWidth \* 0.5 tutBtn.y = 200 menuGroup:insert(tutBtn) 

-- tutorialmenu.lua local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects=nil director:changeScene("menu") -- Works, goes back to the menu everytime. end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

-- tutorial1.lua local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects = nil director:changeScene("tutorialmenu") -- Doesnt work, goes to menu end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

Hi Silky,

By chance, are you not removing the current Runtime “key” listener right before you leave the previous scene? I notice it’s being added each new scene, so maybe there’s some weird kind of “stacking” behavior is going on, where it’s sending multiple events on the press of the key, and going to a scene you don’t intend it to.

Brent

Hey thanks Brent,

I’ve tried the format below to remove the Runtime, proper navigation didn’t work.

local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects = nil Runtime:removeEventListener("key", onKeyEvent) director:changeScene("tutorialmenu") -- Doesnt work, goes to menu end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

I solved the navigation problem by adding a separate function and adding a timer in the onKeyEvent. I have absolutely no clue why that works but I’m thankful. I hope that’s a proper way to remove Runtimes.

local function goBack() display.remove(Objects);Objects=nil Runtime:removeEventListener("key", onKeyEvent) director:changeScene("tutorialmenu", "crossfade") end local function onKeyEvent( event ) local returnValue = true if (event.phase=="up" and event.keyName=="back") then timer.performWithDelay(100,goBack,1) end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

 

The back button has an up and down phase. When you tap the button, the event handler will fire twice, just like a touch handler, try adding an: If event.phase == “ended” then end block around your code

Hi Silky,

Is “Menu” in your code actually represented by “main.lua”?

In this line…

[lua]

director:changeScene(“scene”)

[/lua]

…what does “scene” represent? I can’t recall exactly how Director handles this, but “scene” should mean “scene.lua” as far as I know, and perhaps if that module doesn’t exist, it defaults to “main.lua”.

Brent

I put “scene” to represent the scenes which would be “scene1.lua”, etc. Here’s a tree of what I have, “<–” represents my back key behaviors.

main.lua --> menu.lua --> tutorialmenu.lua --> tutorial1.lua
                                    <--  tutorialmenu.lua
                                    <-----------------------------  tutorial1.lua      Goes back 2 scenes instead of the previous.

So instead of “tutorial1” going back to “tutorialmenu”, it goes all the way back to “menu”. And this goes for every tutorial module I have, “tutorialmenu” is the only one that goes back to the previous scene.

 

-- menu.lua local function toTutorials( event ) if event.phase == "ended" then display.remove(Objects);Objects=nil director:changeScene("tutorialmenu", "crossfade") end end tutBtn = widget.newButton { width = 429, height = 118, defaultFile = "tutBtn.png", overFile = "tutBtn-over.png", id = "tutBtn", onEvent = toTutorials, } tutBtn.x = display.contentWidth \* 0.5 tutBtn.y = 200 menuGroup:insert(tutBtn) 

-- tutorialmenu.lua local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects=nil director:changeScene("menu") -- Works, goes back to the menu everytime. end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

-- tutorial1.lua local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects = nil director:changeScene("tutorialmenu") -- Doesnt work, goes to menu end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

Hi Silky,

By chance, are you not removing the current Runtime “key” listener right before you leave the previous scene? I notice it’s being added each new scene, so maybe there’s some weird kind of “stacking” behavior is going on, where it’s sending multiple events on the press of the key, and going to a scene you don’t intend it to.

Brent

Hey thanks Brent,

I’ve tried the format below to remove the Runtime, proper navigation didn’t work.

local function onKeyEvent( event ) local returnValue = true local phase = event.phase local keyName = event.keyName if "back" == keyName then display.remove(Objects);Objects = nil Runtime:removeEventListener("key", onKeyEvent) director:changeScene("tutorialmenu") -- Doesnt work, goes to menu end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

I solved the navigation problem by adding a separate function and adding a timer in the onKeyEvent. I have absolutely no clue why that works but I’m thankful. I hope that’s a proper way to remove Runtimes.

local function goBack() display.remove(Objects);Objects=nil Runtime:removeEventListener("key", onKeyEvent) director:changeScene("tutorialmenu", "crossfade") end local function onKeyEvent( event ) local returnValue = true if (event.phase=="up" and event.keyName=="back") then timer.performWithDelay(100,goBack,1) end return returnValue end Runtime:addEventListener( "key", onKeyEvent )

 

The back button has an up and down phase. When you tap the button, the event handler will fire twice, just like a touch handler, try adding an: If event.phase == “ended” then end block around your code