How to lock a device "back" button?

I added a few transitional scenes between the main levels, nothing special happens on them, but if press the physical button “back” on the device (or emulate), the game will crash or close.

To prevent this on the main levels, I set everywhere with differen actions:

function onKeyEvent( event ) -- Some Code Here end

For example, on the menu.lua level I have the question “exit: yes/no”.

But at transitional scenes, I do not need special actions. Is there a way to block or ignore commands from this button?

How do you prevent physical keys in short transitional scenes 10-120 seconds long?

The easiest approach is to have a conditional check in your key event function. If the check fails, i.e.  canExit  is false, then if back button is pressed, it’ll just be captured but ignored by Corona.

local canExit = false local function onKeyEvent( event ) if canExit then -- Your "exit game" code else if keyName == "back" then return true else return false end end return false end Runtime:addEventListener( "key", onKeyEvent )
1 Like

Thanks for advice! I will try it soon.

if (Application.platform == RuntimePlatform.Android)
2.
        {
3.
            if (Input.GetKey(KeyCode.Escape))
4.
            {
5.
                // Insert Code Here (I.E. Load Scene, Etc)
6.
                // OR Application.Quit();
7.
 
8.
                return;
9.
            }  //this the way to program the back button.hope it will solve your issue.:heart:

XeduR @Spyric thanks for the advice, I suspected, that I must write this code everywhere, but I kept hope for a one-click solution. Right now game are not crushing or closing, but I have another question

Why if I put this code

local function onScreenButton( keyEvent ) --print ("("..keyEvent.keyName.." , " .. keyEvent.phase ..")") if keyEvent.keyName  == "back" and keyEvent.phase == "up" then print ('Yes, yes, yes!') return true    end    return false end

somewhere in between

function scene:create( event ) \*\*\*\* end

it continue to work after removing that scene? Even after removing maaanny scenes after the initial. (I test the position in menu).

But it doesn’t works if I put it in the area before scene:create, which in Docs described as 

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

Does it mean, that scene:create can’t contain functions?

It doesn’t really matter where you put it, but main.lua is the simplest and most logical location for it. You don’t need to add it to several locations.

When you create a Runtime listener, then if you want to get rid of it, you need to remove it manually. Read the “Important” box here: https://docs.coronalabs.com/guide/events/detectEvents/index.html#registering-events

scene:create() method can contain functions, but placing them there is probably not the most optimal way. With this function specifically, it isn’t the place where you want to put it.

Well, I tried this first, but I have scene-specific code, which exists only in main game scenes and also slightly changes between them, so in structure with flags

if canExitFlag == 'menu' then    gotoExit () elseif canExitFlag == 'scene1' then    PauseScene () elseif canExitFlag == 'overlay1' then    ReturnParent () elseif canExitFlag == 'scene2' then    PauseScene () elseif canExitFlag == 'overlay2' then    ReturnParent () -- \*\*\* so on \*\*\* else --do nothing end

I got an error because functions don’t exist in main.lua (they all defined as local in concrete scenes) and when I define all of them globally I lose stability in some cases, apparently, because functions after the first call remaining in memory and have the same name. Or not.

In fact, I decided not to dig this question, now it’s hard to specify all stages from different scenes, all flags and test everything again when it works already. So I just add new code in transitional scenes.

Of corse I remove all listeners at the scene:destroy () part of the code. Thanks for clarifying that this function is very specific.

Well, if you create those functions in your scenes, then they are obviously out of main.lua’s scope. What you had asked me originally was “how to prevent player from using back button on Android”, but now you have all sorts of functions set.

If you want fancy custom functions to occur when you press the back button in different scene, then the best way to achieve that is to add a function that handles key events to each of your scenes. However, this is far from optimal and you need to remove and add the Runtime listeners every time you exit/enter a scene. But again, I have absolutely no idea as to why you would want or need something like this.

Since you use  composer , then you could simply make a  composer.canExit = true/false parameter that you toggle on and off between scenes. Then, if you want to… let’s say return to the previous scene, you could again just use composer parameters to achieve that.

-- main.lua local composer = require("composer") composer.canExit = false composer.prevScene = false local function onKeyEvent( event ) if composer.canExit then -- Your "exit game" code elseif composer.prevScene then composer.gotoScene( composer.getSceneName( "previous" ) ) else if event.keyName == "back" then return true end end return false end Runtime:addEventListener( "key", onKeyEvent ) -- someScene.lua function scene:show( event ) if event.phase == "did" then composer.canExit = true end end

With composer.prevScene, you could set that in some cases, if back button is pressed, then the game will go to the previous scene instead of exiting (or doing nothing). You can also add references to other functions composer table, etc.

Still, the thing is that players don’t expect to control the game with the back button.

And finally, if you need custom functionality in your other scenes, then why not just leave the back button blocking function alone in main.lua and write those specific functions in their scenes? Nothing is stopping you from writing more functions in your scene that are scene specific, or perhaps write a module that you could require in all of your scenes?

Yes, there is an inaccuracy in my words.

I have UI-buttons, by clicking which player can do everything he needs to play. But when I started testing on devices, I found crashes when I click on the on-screen or physical buttons on the phone. So I started adding code to every main scene that tracks clicks. But it contains only one (1) function:

local function onScreenButton( keyEvent )   if keyEvent.keyName  == "back" and keyEvent.phase == "up" then       --Exit (), GamePause (), GameResume () and so on, what I need in a specific scene         return true     end return false end

Specific scene code, which I spoke about earlier, set in that functions. CO: this is convenient because the game can end for various reasons, but I only need to call GamePause ().

So when I started adding intermediate and transition scenes, I became interested in the question of whether copy-pasting can be dispensed with. 

And I agree that constantly blocking clicks in main.lua is better than adding/removing the same at all scenes (crushes are possible when the click occurs at the moment when the listener is not yet added).

But I don’t need to transfer any specific data to the tap listener in main.lua, because it will be just duplicating. All I need from main.lua, is to call a function in a specific scene, and if I make that functions global, like this, it works:

local function onScreenButton( keyEvent ) if keyEvent.keyName  == "back" and keyEvent.phase == "up" then if composer.sceneName == 'menu' then Exit() elseif composer.sceneName == 'scene1' then GamePause () elseif composer.sceneName == 'ovelay1' then GameResume () --etc end return true     end return false end

Maybe I could transfer local functions?

Right now I use both - one global function button blocking alone for everything in main.lua, and additional local button blocking functions in the main game scenes to call local functions Exit (), GamePause (), GameResume () inside.

And this duplicating doesn’t look good - like more code vs more global functions.

Sorry, if I bother you, I just want to choose an optimal option without extra code, avoid globals and data transfer.

Thanks to this post I found a way, how to use composer and local functions without making them global.

So you found a post that does what I suggested you should do. :stuck_out_tongue:

Glad to hear you got things sorted!