Runtime event listener not being removed

I’ve added a runtime listener to use Android’s hardware back button in storyboard as follows:

[lua]

local onKeyEvent = function(event)

    local keyname = event.keyName

    if (event.phase == “up” and event.keyName==“back”) then

        storyboard.gotoScene(“scripts.scene1”)

    end

    return true

end


function scene:enterScene(event)

    if system.getInfo( “platformName” ) == “Android” then  

        Runtime:addEventListener( “key”, onKeyEvent )

    end

end


function scene:exitScene(event)

end


function scene:destroyScene(event)

    if system.getInfo( “platformName” ) == “Android” then

        Runtime:removeEventListener(“key”, onKeyEvent)

    end

end

[/lua]

However, upon the destroyScene event, the event listener is not being removed. Why is this? I’ve tried changing the code to 

[lua]

local onKeyEvent = function(event)

    local keyname = event.keyName

    if (event.phase == “up” and event.keyName==“back”) then

        storyboard.gotoScene(“scripts.scene1”)

    end

    return true

end


function scene:enterScene(event)

    if system.getInfo( “platformName” ) == “Android” then  

        local Runtime:addEventListener( “key”, onKeyEvent )

    end

end


function scene:exitScene(event)

end


function scene:destroyScene(event)

    if system.getInfo( “platformName” ) == “Android” then

        local Runtime:removeEventListener(“key”, onKeyEvent)

    end

end

[/lua]

but this gives me errors when trying to build the app for android. Any suggestions?

FYI, in case you missed it, the change I made was adding “local” to the runtime event listener declarations. 

storyboard.gotoScene() only triggers the exitScene() function, NOT destroyScene().

From the code you have posted, you only ever use gotoScene(), and never call purgeScene or removeScene. So the destroyScene function never gets called, and your runtime listener never gets removed.

Move the “removeEventListener” call into the exitScene() function, and that should solve the problem.

Have this now, but it still does not remove the event listener:

[lua]

function scene:enterScene(event)

    if system.getInfo( “platformName” ) == “Android” then  

        Runtime:addEventListener( “key”, onKeyEvent )

    end

end


function scene:exitScene(event)

    if system.getInfo( “platformName” ) == “Android” then

        Runtime:removeEventListener(“key”, onKeyEvent)

    end

end

[/lua]

FYI, in case you missed it, the change I made was adding “local” to the runtime event listener declarations. 

storyboard.gotoScene() only triggers the exitScene() function, NOT destroyScene().

From the code you have posted, you only ever use gotoScene(), and never call purgeScene or removeScene. So the destroyScene function never gets called, and your runtime listener never gets removed.

Move the “removeEventListener” call into the exitScene() function, and that should solve the problem.

Have this now, but it still does not remove the event listener:

[lua]

function scene:enterScene(event)

    if system.getInfo( “platformName” ) == “Android” then  

        Runtime:addEventListener( “key”, onKeyEvent )

    end

end


function scene:exitScene(event)

    if system.getInfo( “platformName” ) == “Android” then

        Runtime:removeEventListener(“key”, onKeyEvent)

    end

end

[/lua]

@zabace. Have you found a solution to this issue ? 

@zabace. Have you found a solution to this issue ? 

I have the same issue. Is there a solution for this?

I’m not sure why it’s not removing the event listener with the storyboard.* API, however I’m using the new composer.* API and it removes the event listener as expected.

I just changed to composer but it did not help.

Very weird, I have the following composer.* API code which works as expected.

function scene:hide(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:removeEventListener("key", onAndroidKeyEvent); end end

What does your onAndroidKeyEvent function and EventListener look like?

It looks like this. I’m using the back key to close an overlay.

local onAndroidKeyEvent = function(event) local key = event.keyName; local phase = event.phase; if (key == "back") then if (phase == "down") then composer.hideOverlay(false, "slideDown"); end return true; end return false; end

Also what build are you using?

2259

Is that listener and function in:  function scene:create( event ) ?

The structure of my scene is as follows (stripping out a lot of code)
 

local composer = require("composer"); local scene = composer.newScene(); local onAndroidKeyEvent = function(event) local key = event.keyName; local phase = event.phase; if (key == "back") then if (phase == "down") then hideOverlay(false, "slideDown"); end return true; end return false; end -- ------------------------------------------------------------------------------- function scene:create(event) local sceneGroup = self.view -- create stuff end function scene:show(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:addEventListener("key", onAndroidKeyEvent); end end function scene:hide(event) local sceneGroup = self.view; local phase = event.phase; local parent = event.parent; if (phase == "will") then Runtime:removeEventListener("key", onAndroidKeyEvent); end end function scene:destroy(event) local sceneGroup = self.view; end -- ------------------------------------------------------------------------------- scene:addEventListener("create", scene); scene:addEventListener("show", scene); scene:addEventListener("hide", scene); scene:addEventListener("destroy", scene); -- ------------------------------------------------------------------------------- return scene;

This is the structure of my scene which does not remove the “key” listener. Do you have any ideas why this would not work?

local composer   = require(“composer”);

local scene      = composer.newScene();


function scene:create(event)

    local sceneGroup = self.view

    

    local onAndroidKeyEvent = function(event)

        local key = event.keyName;

        local phase = event.phase;

        if (key == “back”) then

            if (phase == “down”) then

                hideOverlay(false, “slideDown”);

            end

        

            return true;

        end

        return false;

    end

    

    Runtime:addEventListener(“key”, onAndroidKeyEvent);

    – create stuff

end

function scene:show(event)

    local sceneGroup = self.view;

    local phase = event.phase;

    local parent = event.parent;

    if (phase == “will”) then

        –

    end

end

function scene:hide(event)

    local sceneGroup = self.view;

    local phase = event.phase;

    local parent = event.parent;

    if (phase == “will”) then

        Runtime:removeEventListener(“key”, onAndroidKeyEvent);

    end

end

function scene:destroy(event)

    local sceneGroup = self.view;

end