Bug with back button?

Hi I am doing some testing using the native back button on android and getting a bit of odd results. Any help on this is appreciated, i might have found my first Corona bug (probably not), but still, exciting times! 

I have a back button image programmed into “Screen 2” using an event listener (an image that if you click on takes you to “Screen 1”).  I am on screen 1 then go to screen 2 then click back using the back button in the game then do this again 3 more times no problem.  

Now if im in screen 1 then go to screen 2 and use the native android back button it does go back but does not use screen transitions and all audio channels get permanently muted, then if i go to screen 2 again then back to screen 1 it will crash second time around.  This exact behavior is consistent not just one time.

In the end both the native back button and the event listener of the image call the same exact function “goToHome()” and are right next to eachother in the code so there really should be no difference with the result.  The broken audio is telling me that maybe my “removeObjects()” function that gets called within goToHome is not completing when using the native back button.

--Code for native back button local function onKeyEvent2( event ) if ( event.keyName == "back" ) then goToHome() end return true end Runtime:addEventListener( "key", onKeyEvent2 ) --Back button programmed in the game backButton:addEventListener("touch", goToHome)

That’s not quite right. You’re ignoring phases. Your code may call gotToHome() twice in a row.

You also probably want to stop listening for that event or the next time you press the back button your code will execute again.

 

local onKeyEvent onKeyEvent = function( event ) local phase = event.phase local keyName = event.keyName if( (keyName == "back") and (phase == "down") ) then Runtime:removeEventListener( "key", onKeyEvent ); goToHome() end return true end Runtime:addEventListener( "key", onKeyEvent );

Hey Rob,

Thanks for the insight and all makes much more sense didnt know there were phases involved :slight_smile:

I do have one problem which is that it does not work as in I just get kicked out of the app.  I fixed the “if(” to “if (” that you have but no luck.  Maybe a different phase I should be looking for?  Also i tested with the old code by putting a print statement and yes you were right (as always) it was getting called twice :slight_smile: .

Rob? :)  

This is “Ed”, aka the “Roaming Gamer”

I don’t understand what you mean by "it does not work as in I just get kicked out of the app. "

Do you mean, the first time you press ‘back’ or the second time?

If the second time, are you setting up the listener again?

I assume you’re using composer.*

If you’re using composer.* download this: https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/composer_scene_manager.zip

Then look at example 15.

You can run this in the simulator and use the ‘escape’ key as way to test for the ‘back’ key.

This example includes a sample scene framework that supports multiple last-scene navigation using the back/escape button/key.

hahaha soo sorry just saw the R and I talk with Rob all the time and hes always right haha but I have gotten at least 20 answers off the forum from posts from you as well to know you are always right all the time too!!!

no the problem is that I am kicked out of the game completely as if it were “return false”

Try my example framework and see if you can apply the code and module  to your game/app

PS - I make mistakes. But I appreciate the confidence. :slight_smile:

Went through your example at number 15.  They do not use the native back button in here.  I tested the back button here and when i use the native back button I am just kicked out of the application.  I also went through the code on all 5 scenes and the word “key” is not found in all of them and this is a static word thats needed for the native back button to work “Runtime:addEventListener( “key”, onKeyEvent );”

Example 15 does use the native back button.  I’m simply not doing it the way you expect me to.

You’re looking in the wrong place.  Look in the file android.lua 

That is a module I use to create a temporary listener per scene.

This is how I set it up  in scene1:

 if( not backHandler ) then backHandler = android.new( { debugEn = true, title = "Quit Game?", msg = "This will exit the game.\n\nAre you sure you want to quit?" } ) end

This is how I do it in scene2:

 if( not backHandler ) then backHandler = android.new( { debugEn = true, onBack = onBack } ) end later you will see the definition of onBack as... onBack = function ( self, event ) composer.gotoScene( "ifc.scene1", options ) return true end

I just built it with 2018.3363 and tested it on my device.

Here is the APK I built. https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/android_back_nav.zip

Thanks sooo much again.  Its getting super late by me and I will take a look at this first thing from work tomorrow and update.  One tiny thing off subject if I may.

Small rant looking for resources :slight_smile:

Although all the examples in the 15 examples are a little basic they show me a lot of things that I should be applying to my code to make it more efficient and new ideas on how to code.  I have only looked at example 15 so far but the whole file structure and coding structure in general of everything is new to me.  Also you said “That is a module I use to create a temporary listener per scene.”  I have no idea what that means but if I look through this code more deep I will understand everything thats going on and thats enough for me.

I started programming 6 months ago and through teaching myself I made a full game with ads and iap, on ios, android and kindle that I published.  Not bragging or something im getting somewhere :slight_smile: , when I look through my code I actually almost get sick looking at how inefficient and mistakes I have but im always adding and adding and not fixing.  I am doing one more release v2.0 if you will, then I am recoding my game completely before I add anything.

What im getting to is if you have more of these examples I would love to look them over before I recode my whole game to really see the correct way for everything im already doing so I dont have to recode twice :slight_smile:

Don’t worry about re-coding.  That is how you learn to do it better next time.

Learning to program and getting better at it is an incremental thing. 

I’ve been coding for 38 years and I can still stand to improve.  Also, there are many folks here who write more professional looking code that I do.

Often we have to do it wrong or less than efficiently to understand why our code needs to improve.  Only then can we make the leap to improving it.

The key takeaway here is, that I’ve created a module (in android.lua) that I use to set up and later destroy listeners per-scene.  These listeners each do ‘custom’ things specific to that scene.

PS - Please note: 

A. That work is a little dated.  I do things a little differently now.  That said they are still decent examples.

B. Those example are mostly slim and sparse so you can walk through them and understand the layout of the files and the structure of how I set up for so scope and visibility are not issues.

C. Pay particular attention to the fact that I may do different and important work in these listeners:

  • create()
  • willEnter()
  • didExit()

yes these examples are great.  The whole willEnter didEnter is new to me as I am using the will and did in scene show which you have as generally not to touch below that line :slight_smile: .  I have been looking over these examples past half hour liking a lot of the core ideas.  Some very new concepts for me such as creating an array and storing functions in them.  Dont quite get the purpose of that one. Easier to destroy?  ie:

local handler = {}

function handler.key( self, event )

function handler.activate( self )

function handler.deactivate( self )

I have tried to apply your code to my code regarding the back button and worst part is im not getting errors its just still acting as if return is false.  Problem might be because of something else.  Have some testing to do with this ahead of me but sure i will crack it thanks to this  :slight_smile: .  

Feel free not to reply to this one as its probably super basic but how does or work when assigning a variable:
params.title = params.title or “Exit?” 

If there is a core programming concept in any of the questions that im missing please just tell me the name of it so I can do some research on that concept.

edit:

So for now my temporary fix which works but I promise will get fixed the right way hahaha is the code I had the old way but force it to only happen once which again I know sucks but will get fixed :slight_smile:

local keyFirstTime=0 local function onKeyEvent2( event ) if ( event.keyName == "back" and keyFirstTime==0) then keyFirstTime=1 goToHome() end return true end Runtime:addEventListener( "key", onKeyEvent2 )

That is how you create a module.
 
i.e. This in a file (let’s call it myModule.lua) makes that file a module:

local public = {} function public.doit()   print("Yo running doit()") end return public

then later,

local mod = require "myModule" mod.doit()

A module (in Lua) is essentially nothing more than a script file with a table defined near the top, with functions attached to the table, and then the table reference returned at the bottom.

If you require() this module, it gets loaded into memory permanently. Subsequent requires do not re-load the script, but get the handle which has been stored for you in memory.

This is a fundamental concept in Lua and Corona game dev. You won’t get far without understandsing this thoroughly. i.e. While you can create monolithic designs, the module approach is far better.

Ok amazing that makes much more sense :slight_smile: I started reading a little about modular designs when i hit the 200 variable limit but learned how to clear a lot of that differently.  It just hit me how much cleaner and efficient this could make my code.  Im guessing you wouldnt use the creation of images in a modular way though.

I will do more research and build some small examples on this topic but really appreciate the time you have given me immensely.

Just a quick heads up as it might help someone else.  In the end I was having a ton of problems with this on obvious things not working.  

The problem is that the simulator back button performs much different behavior than a real device.  Should have been obvious to me.

Now that I know its a simulator vs native device problem im actually pretty sure there is a bug.  I go to screen 2 from screen 1 then click the back button and I do go back to screen 1 correctly but the back button for screen 1 is also being triggered. So basically im in screen 2 then click the back button and I go to screen 1 and a dialog box pops up asking if i want to leave the game. 

I do have the remove event listener in place and I even tried to put the remove event listener in scene:hide did / will and tried in destroy but still happens.

Screen 1

local function onKeyEvent( event ) local phase = event.phase local keyName = event.keyName if( (keyName == "back") and (phase == "down") ) then Runtime:removeEventListener( "key", onKeyEvent ) local function onComplete( event ) if ( event.action == "clicked" ) then local i = event.index if ( i == 1 ) then native.requestExit() elseif ( i == 2 ) then end end end local alert = native.showAlert( "Exit Candy Words?", "Are you sure you want to exit Candy Words?", { "Yes", "No" }, onComplete ) end return true end Runtime:addEventListener( "key", onKeyEvent )

Screen 2

local function onKeyEvent2( event ) local phase = event.phase local keyName = event.keyName if( (keyName == "back") and (phase == "down") ) then Runtime:removeEventListener( "key", onKeyEvent2 ) goToHome() end return true end Runtime:addEventListener( "key", onKeyEvent2 )

Found an answer to this here that is working great!!

I am using the approach of putting the back button key listener in main.lua and then calling a function in that scene to do a specific thing.

in main

local callingScene = composer.getScene( composer.getSceneName( “current” ) )

callingScene:backButton()

in all other scenes

function scene:backButton()

–Code to happen when back button is pressed specific to that scene

end

https://forums.coronalabs.com/topic/70345-event-key-back-and-composer/

That’s not quite right. You’re ignoring phases. Your code may call gotToHome() twice in a row.

You also probably want to stop listening for that event or the next time you press the back button your code will execute again.

 

local onKeyEvent onKeyEvent = function( event ) local phase = event.phase local keyName = event.keyName if( (keyName == "back") and (phase == "down") ) then Runtime:removeEventListener( "key", onKeyEvent ); goToHome() end return true end Runtime:addEventListener( "key", onKeyEvent );

Hey Rob,

Thanks for the insight and all makes much more sense didnt know there were phases involved :slight_smile:

I do have one problem which is that it does not work as in I just get kicked out of the app.  I fixed the “if(” to “if (” that you have but no luck.  Maybe a different phase I should be looking for?  Also i tested with the old code by putting a print statement and yes you were right (as always) it was getting called twice :slight_smile: .

Rob? :)  

This is “Ed”, aka the “Roaming Gamer”

I don’t understand what you mean by "it does not work as in I just get kicked out of the app. "

Do you mean, the first time you press ‘back’ or the second time?

If the second time, are you setting up the listener again?

I assume you’re using composer.*