Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Event key "back" and Composer
Started by DanielApps Sep 25 2017 04:37 PM

25 replies to this topic
event key back and composer event key event key back

Best Answer roaminggamer , 10 October 2017 - 11:06 AM

Oh, one more note.  That kind of an error should be reproduce-able on the simulator.

 

 

To get a little more info, do this at the top of main.lua.

local composer = require "composer"
composer.isDebug = true

To try to force an error do this when running in the simulator:

local composer = require "composer"
composer.recycleOnSceneChange = true

-- Not exercising same algorithm, but let's see what happens.

[TOPIC CONTROLS]
Page 1 of 2 1 2
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

I'm having trouble making the native button "back" on the android work correctly.
I tried everything and searched all over the subject on the internet and could not find a solution.
 
The app I'm creating has a button that rewinds scenes created with Composer.
But I would like to make this possible also through the Android back button.
 
Everything I have tried does not work correctly and the event propagates through all scenes because I am not able to cancel/remove the "Runtime: addEventListener" in each scene.
 
Here is part of my code to try to implement that function:
 
 
local function onKeyEvent( event )

	local platformName = system.getInfo( "platformName" )
		if ( platformName == "Android" ) then
			if ( event.keyName == "back" ) then
				
				composer.gotoScene( "scene1" )
				composer.removeScene( "scene2" )
				Runtime:removeEventListener( "key", onKeyEvent )
				
				return true
			end
		end
	 				
	return false
end
--
--
	
Runtime:addEventListener( "key", onKeyEvent )

I appreciate if you can give me a solution that works and can be implemented within the pages I created with Composer.

Thank you,

Daniel



[TOPIC: post.html]
#2

Blex

[GLOBAL: userInfoPane.html]
Blex
  • Corona Geek

  • 1,199 posts
  • Corona SDK

What do you mean by it does not work correctly? What is occurring that you do not want to happen or vice versa?

 

(1000th post, yay!)



[TOPIC: post.html]
#3

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

Yes, we will need more details on what "doesn't work"... does it even reach the function? Or is some condition in your code causing it to never even get there?

 

Brent



[TOPIC: post.html]
#4

yvandotet

[GLOBAL: userInfoPane.html]
yvandotet
  • Contributor

  • 185 posts
  • Corona SDK

Don't forget that there are two phases during pushing a button, a " up " and " down " phase.

 

So when you just touch the back button, the down phase happens and removes the listener, so when your finger leave the back button, the up phase happens but the Runtime key listener is already removed.



[TOPIC: post.html]
#5

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Actually, the button (back of Android) works, but in a strange way.
Every time I do a new build and do tests I notice the following:
 
I have five scenes inside the composer.
If I'm in scene 5, when I use the "back" button instead of going back to scene 4, it ends up going back to scene 3, or sometimes it leaves the application.
 
Or even sometimes it returns from the last scene to scene 1.
 
Or when I do some testing and I use the code in only 1 scene, I realize that the code does not close when the scene exits and spreads to the other scenes.

 


[TOPIC: post.html]
#6

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

You have to disable the listener for the scenes you're not in.  All scenes that have been activated are probably listening for this event.



[TOPIC: post.html]
#7

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Here a sample of the code.

I'm a newbie, someone can explain how to implement or to do it.

 

Thank you,

local composer = require( "composer" )
 
local scene = composer.newScene()
 
-- -----------------------------------------------------------------------------------
-- Code outside of the scene event functions below will only be executed ONCE unless
-- the scene is removed entirely (not recycled) via "composer.removeScene()"
-- -----------------------------------------------------------------------------------
 
-- Here is the function

	local function onKeyEvent( event )

	local platformName = system.getInfo( "platformName" )
		if ( platformName == "Android" ) then
			if ( event.keyName == "back" ) then
				
				composer.gotoScene( "scene1" )
				composer.removeScene( "scene2" )
				Runtime:removeEventListener( "key", onKeyEvent )
				
				return true
			end
		end
	 				
	return false
end
--
--
	
Runtime:addEventListener( "key", onKeyEvent )
 
--
--
-- -----------------------------------------------------------------------------------
-- Scene event functions
-- -----------------------------------------------------------------------------------
 
-- create()
function scene:create( event )
 
    local sceneGroup = self.view
    -- Code here runs when the scene is first created but has not yet appeared on screen
	
	
	--
	--
	--
	--
	-- Here is my code
 
end
 
 
-- show()
function scene:show( event )
 
    local sceneGroup = self.view
    local phase = event.phase
 
    if ( phase == "will" ) then
        -- Code here runs when the scene is still off screen (but is about to come on screen)
 
    elseif ( phase == "did" ) then
        -- Code here runs when the scene is entirely on screen
 
    end
end
 
 
-- hide()
function scene:hide( event )
 
    local sceneGroup = self.view
    local phase = event.phase
 
    if ( phase == "will" ) then
        -- Code here runs when the scene is on screen (but is about to go off screen)
 
    elseif ( phase == "did" ) then
        -- Code here runs immediately after the scene goes entirely off screen
 
    end
end
 
 
-- destroy()
function scene:destroy( event )
 
    local sceneGroup = self.view
    -- Code here runs prior to the removal of scene's view
 
end
 
 
-- -----------------------------------------------------------------------------------
-- Scene event function listeners
-- -----------------------------------------------------------------------------------
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )
-- -----------------------------------------------------------------------------------
 
return scene


[TOPIC: post.html]
#8

bjsorrentino

[GLOBAL: userInfoPane.html]
bjsorrentino
  • Veteran

  • 8,506 posts
  • Corona SDK

Hi @DanielApps,

A few things I can advise based on your code snippet:

 

1. Don't add/activate the Runtime key listener outside/above the Composer "scene event" blocks. It's fine (and correct) that you include the listener function there, but I would only add/activate it within the "show > did" condition because, logically, that's when it matters (IMHO the user shouldn't be able to back out of the scene until the scene is fully visible).

 

2. At the same time, REMOVE (deactivate) the Runtime listener in the "hide > will" condition area, because at that point, the user has clearly decided to leave the scene and they shouldn't be able to re-leave the scene once they're already leaving it (allowing that would cause unpredictable behavior).

 

3. Add the phase detection of either "up" or "down" to the key event, and handle just one of them (not both).

 

I might also ask, what behavior is your goal for users who want to back-out of the app entirely using the back key? Will your app prevent it? Or will you make them back-out all the way to the first home scene before letting them back out of the app? Just something to consider...

 

Brent



[TOPIC: post.html]
#9

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

So far, I am very grateful for the help of everyone.
I will try all possibilities until I get something satisfactory.
 
Regarding your question, Brent, the app already has a return button for the scenes (this app is just for presenting a portfolio), but I'd like to add the native Android button "back".
 
Ideally, the user would return to the first scene and then might suggest a warning like, "Do you really want to quit the application?" Or something like that.
 
But I do not know if I can do this quickly and efficiently, as I said above I'm just an illustrator and beginner in programming.

Thank you!


[TOPIC: post.html]
#10

ojnab

[GLOBAL: userInfoPane.html]
ojnab
  • Contributor

  • 576 posts
  • Corona SDK

@DanielApps

 

Try keeping the back key event stuff out of the composer scenes.

Instead try doing something like this in your main.lua file:

--  main.lua

-- require the composer library
local composer = require "composer"
composer.gotoScene( "scene1" )

-- Key listener
local platformName = system.getInfo( "platformName" )

local function onKeyEvent( event )
    if ( platformName == "Android" ) then
        if event.phase == "down" then
            if event.keyName == "back" then
                local currScene = composer.getSceneName( "current" )
                local prevScene = composer.getSceneName( "previous" )
                if currScene == "firstScene" then
                    -- present an alert asking if the user wants to quit the app.
                elseif prevScene then
                    composer.gotoScene( prevScene )
                end
                return true
            end
        end
    end
end

Runtime:addEventListener( "key", onKeyEvent )


[TOPIC: post.html]
#11

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

@DanielApps,

 

Got this working yet?



[TOPIC: post.html]
#12

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

I'm still encountering some problems.
The solution given by @ojnab works, only that a problem occurs, the scene only goes back and forth.
 
For example, I have five scenes, if I am in scene 5 the "back" button only returns to scene 4 and if I press again, it returns to scene 5.
 
The "back" button does not return scene by scene until the first scene is reached.


[TOPIC: post.html]
#13

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

I have a bunch of composer.* examples here: https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/composer_scene_manager.zip

 

I just added a new example doing basically what you want to do with a module. 

 

Download from the above link and see example 15_android_back_nav.

 

When you poke through the scene files (found in ifc/ folder), look for the marker: BACK_HANDLER

 

See the module android.lua for how I did this.

 

To use the module, do the following (in your scene files)

 

Normal Scene File

 

1. Somewhere towards top of file:

local android = require "android"
local backHandler

2a. In create() method of your scene, If you intend to exit app from this scene:

   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

2b. In create() method of your scene, If you intend to return to another scene:

-- This assumes onBack is a function that calls the right composer functions to go back to another
-- scene from this one 
-- 
-- AND... that onBack has already been defined by this point
--
if( not backHandler ) then
   backHandler = android.new( { debugEn = true, onBack = onBack } )
end

-- Tip: debugEn true enables the escape key so you can test this in the simulator

3. In the 'did' phase of show() method for your scene.

backHandler:activate() -- BACK_HANDLER	

5. In the 'will' phase of hide() method for your scene.

backHandler:deactivate() -- BACK_HANDLER

Overlays

Overlays are a little trickier because they don't trigger the will or did phases of the scene that is being overlayed.  So you have to know this and act accordingly.

 

This example shows how to handle this, and I won't show you here.  Just look for the markers: BACK_HANDLER

 

 

Warning

My scene files are a LITTLE different from the ones Corona shows.  I have split the show() and hide() methods into:

  • willShow()
  • didShow()
  • willHide()
  • didHide()

I do this because I like my code kept clearly separate.

 

 

Examine my samples carefully (see code at very bottom) and you'll see how I did this.



[TOPIC: post.html]
#14

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

In action...

 



[TOPIC: post.html]
#15

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

 
Unfortunately, this still does not work.
 
When I am in scene 3 and I use the "back" button, it only shows the warning screen (Exit? Are you sure? Yes - No), instead of going back to scene 2.
 
When I am in scene 1 and press the "back" button, the warning screen (Quit Game? ... Yes - No) appears.
 
If I select "Yes" the application is not closed.


[TOPIC: post.html]
#16

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

Double and triple check your usage.  

 

Not exiting app while in simulator or on phone?

 

If in simulator, no prob.  It is calling:

native.requestExit()

That should exit the app while on Android though



[TOPIC: post.html]
#17

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Not exiting when on the phone, I do not know how to test this on the simulator.
I tested your example (15-android-back-nav) and realized that on the last screen it also does not exit the application.


[TOPIC: post.html]
#18

Benzeliden

[GLOBAL: userInfoPane.html]
Benzeliden
  • Enthusiast

  • 80 posts
  • Corona SDK

 

Not exiting when on the phone, I do not know how to test this on the simulator.
I tested your example (15-android-back-nav) and realized that on the last screen it also does not exit the application.

 

On windows simulator you can use Hardware > Back menu option (or Alt + Left arrow shortcut)



[TOPIC: post.html]
#19

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Thank you for your help, Benzeliden.



[TOPIC: post.html]
#20

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

@Daniel,

 

0. Please re-download the example.   I updated it further and fully tested it on a device.

 

 

1.  You must have missed it, but I stated that debugEn = true in the new() call will allow you to use the 'escape' key to test back.  Still you can use the suggestion Benzeliden gave too.  I just like simple single keystrokes when testing.

 

2. I found and fixed an issue/bug in the module.  This caused the 'exit' call to fail on deviecs.  I had the code out of order:

Was like this:

        local alert        
        alert = native.showAlert( params.title, params.msg, { "NO", "YES" }, onComplete )
        local function onComplete( event )
            if "clicked" == event.action then
                local i = event.index
                if 1 == i then
                    native.cancelAlert( alert )
                    alert = nil
                elseif 2 == i then
                    if( params.onExit ) then params.onExit() end
                    native.requestExit()
                end                        
            end
        end

-- ISSUE?  onComplete wasn't defined before creation of alert

Fix:

        local alert        
        local function onComplete( event )
            if "clicked" == event.action then
                local i = event.index
                if 1 == i then
                    native.cancelAlert( alert )
                    alert = nil
                elseif 2 == i then
                    if( params.onExit ) then params.onExit() end
                    native.requestExit()
                end                        
            end
        end
        alert = native.showAlert( params.title, params.msg, { "NO", "YES" }, onComplete )

3. No matter what you do (short of calling os.exit()), you cannot test exiting the app in the simulator.

 

4. This update includes the following changes:

  • scenes changed to: 1,2,3,4,5, options
  • scene 1 leads to 2 and 3
  • scene 2 leads to 4 or back to 1
  • scene 3 leads to 5 or back to 1
  • scene 4 leads back to 2
  • scene 5 leads back to 3

This will let you fully test the idea of back button to go back to last scene.



[TOPIC: post.html]
#21

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Thank you, roaminggamer!
 

I'm going to need some time to assimilate your code and see how I can make it work inside the code I've made.
 
I'm a beginner and some things are a bit difficult for me, but I need to learn all this and overcome all the challenges, as I have several ideas to put into practice.
 
As soon as I have news, I'll be posting here. :)
 
Daniel


[TOPIC: post.html]
#22

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Recently I have worked on my App again and I can say that all advice was very helpful (mainly the roaminggamer tips ).
My App works now, but when I'm navigating for the scenes I receive a runtime error.
 
"Runtime Error
 
/Users/jenkins/slaveroot/workspace/template....composer.lua1583: attempt to call local "lruScene"  (a string value)"
 
 
I tried to fix it, but I don't know where the failure is occurring.
 
Screenshot_2017-10-09-18-54-00.png?dl=0


[TOPIC: post.html]
#23

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

Are you removing scenes or destroying them?  That may be the source of the issue.

 

Also, please list the composer.* functions you're using.  i.e composer.gotoScene(), composer.???

 

Finally, are you using overlays?  

 

If I coded composer.* lruScene would literally mean 'least recently used scene'. 

 

This would then be used in automatic scene caching and cleaning code.

 

Following this 'logic', there may be an issue occuring when composer tries to remove a scene, which may in turn be caused by the way you're maintaining them.

 

I think you may need to pay someone to look into this for you if you can't resolve it.

 

PS - I updated this post because I brain-farted my last response.  LRU is a well established caching algorithm term and concept in case you were curious.


Edited by roaminggamer, 10 October 2017 - 11:03 AM.


[TOPIC: post.html]
#24

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,591 posts
  • Corona SDK

  Best Answer

Oh, one more note.  That kind of an error should be reproduce-able on the simulator.

 

 

To get a little more info, do this at the top of main.lua.

local composer = require "composer"
composer.isDebug = true

To try to force an error do this when running in the simulator:

local composer = require "composer"
composer.recycleOnSceneChange = true

-- Not exercising same algorithm, but let's see what happens.


[TOPIC: post.html]
#25

DanielApps

[GLOBAL: userInfoPane.html]
DanielApps
  • Observer

  • 19 posts
  • Corona SDK

Hi, roaminggamer!

 

I was able to solve the problem, this was occurring (I think :)) because of an unfixed "Timer" and a function that was previously outside the Composer. But I found the error strange because it does not point to anything concrete inside the code.
 
I added "CancelTimer ()" in your function and that's it.
 
onGotoScene3 = function ( self, event ) 
	composer.gotoScene( "scene3")
	cancelTimer()
	return true
end


Now I think I've got it all figured out.
Thank you very much for your help and for all the other forum collaborators.
I intend to study more to have this immense reasoning that you all have, and for the ease of solving all these problems.
 
Thank you so much!



[topic_controls]
Page 1 of 2 1 2
 
[/topic_controls]