using the timer and delaying a page load

Hi!  I have been struggling with this issue for a few weeks now.  I am trying to load up an interstitial ad between scenes, but the delay between the ads.show call and when it actually shows the ad allows the next scene to be loaded…  this next scene is sometimes on the screen for several seconds before the ad pops up.  When this happens, if a button is pushed before the ad appears, the app crashes…

My current code calls a new adscene when the ad is loaded, and the adscene does nothing but show the ad before calling the next scene.  I have tried putting a timer.performwithdelay function in the adscene to check a flag in the ad listener that tells me when the ad has been shown to try to delay the next scene from loading until after the ad is closed…  however, I guess I don’t understand the timer.  The timer is set to run in a loop until the ad is shown, checking for an adshown flag set by the ad listener, but the next scene continues to be loaded even before the adshown flag is set.

Some basic questions - Does the timer start running and the code following still get executed while the timer loop runs?

I have also tried putting the call for the next scene within the timer listener function, to be called when the adshown flag is set, but this doesn’t work either…

I have tried running this in the scene:create and the scene:show with no success.

Is it maybe that the adshown variable is only checked once on the scene and not reset after the ad listener changes the value?

I appreciate any suggestions or links to some help.  I have looked through the API docs and searched the forum but haven’t found what I need.  I am sure that I am missing something minor and just can’t find what it is… Thank you again for your input.

any ideas???  any suggestions of things to try?

Hello @sonyayllc,

Which ad service/provider are you implementing?

Brent

AdMob v2 - the ads all show as intended, it is just the delay that is the problem.

Do you pre-load the interstitials?

Brent

Yes, I use that in the condition to determine if the adscene should be entered. I only show the ad once every few rounds, so if the count is reached, the ad is loaded. The next round checks if the ad is loaded before going to the adscene where the ads.show is called. The logic seems to check out, but when the adscene does load and calls the ad.show, the next scene starts to load before the ad appears… I am away from my computer but can post the code tomorrow if will help show the flow. Thanks for your help!

Hopefully this helps, these are the main pieces I have been working with.

Here is the adlistener:

--=================================Ad listener============================================ --This listener is for Ads function adListener( event ) local msg = event.response -- just a quick debug message to check what response we got from the library --print("Message received from the ads library: ", msg)   if ( event.isError ) then -- attempt to fetch another ad print("---------------------ad error----------------------") elseif ( event.phase == "loaded" ) then -- an ad was preloaded print("---------------------ad is loaded and ready----------------------") DATA.adshown = false elseif ( event.phase == "shown" ) then -- the ad was viewed and closed print("---------------------ad shown----------------------") if ( event.type == "interstitial" ) then DATA.adshown = true – this is flag being watched end end end

And this is the function that moves from the gamescreen to the adscreen or scorescreen depending on a count, if the ad is loaded, game modes, if the adfree option was purchased, etc.  It also loads the ad when appropriate.  It is a function called in the gamescreen.

--This function is for redirect user to score screen goToScoreScreen = function() audio.stop(gameBgChannel) adsLib:hideAd() for i=1,5 do if ansText[i].text == "" or tonumber(ansText[i].text) == nil then DATA.userAns[i] = "-" else DATA.userAns[i] = tonumber(ansText[i].text) end end   local options = { effect = "fromRight", time = 800, params ={screen="playerDataScreen"} } -- logic to go to the adScene or to the scoreScene -- check if ad is to be displayed if DATA.adPurchased == false and DATA.isRainbow == false then if DATA.displayAds == true then if DATA.counterforad == 2 then    -- number of rounds to skip before displaying ad, 2 for testing if ( adsLib:isLoaded("interstitial") ) then  -- check if the ad is loaded, go to adScene if ad is ready composer.gotoScene("adScreen", options ) else adsLib:loadAd( "interstitial" )     -- this is the ads.loadAd call composer.gotoScene("scoreScreen", options ) -- continue to score end else DATA.counterforad = DATA.counterforad + 1  -- count the round, go to score as normal composer.gotoScene("scoreScreen", options ) end end elseif DATA.isRainbow == true then composer.gotoScene("scoreScreen", options ) end end

And here is the adscreen which shows the ad and then show the scorescreen

gotoscoreScreen = function () composer.gotoScene("scoreScreen", options ) end   timerpause = function() gotoscoreScreen() end   adshowncheck = function(event) if DATA.adshown == true then DATA.adshown = false --adsLib:hideAd() timer.cancel(adtimer) composer.gotoScene("scoreScreen", options ) composer.removeScene( "adScreen" ) -- timer.cancel(adtimer) end end -- ------------------------------------------------------------------------------- -- "scene:create()" function scene:create( event ) local group = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. --print ("wait for ad to close")   adsLib:showAd( "interstitial", nil )  -- this calls the ads.showAd function in adsLib DATA.counterforad = 1    -- reset counter DATA.adcalled = true    --loop until ad is set as 'shown' adtimer = timer.performWithDelay(200,adshowncheck,0)   --timer.performWithDelay(3000,timerpause) --gotoscoreScreen()   end   -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc.   composer.removeHidden() end end

Hi @sonyayllc,

Unfortunately, I can’t fully diagnose this because you’re using the “adsLib” library, which is not something we control (nor am I familiar with its code or functionality). As a general piece of advice, I would suggest that you pre-load the ad as soon as it’s realistically possible, so you have it in the queue for when you need it. For example, load it as soon as the main scene shows, then show it when necessary. As noted in the docs, you can also use the “.isLoaded” call to make sure the ad is loaded and, if not, then you load it up.

Take care,

Brent

This is the adsLib - I understand that you don’t control it, but it isn’t a modification of the ads.* library from Corona, it is just a different location for calling the ads.* functions.  I am not sure why my developer did it this way… it is actually redundant in a way, or at least an extra step in the process.

local DATA = require("gameData") local adsLib = {} --==================================For Advertising ====================================== -- The name of the ad provider. local adsprovider = "admob" -- Your application ID local ads\_appID local ads\_appID\_interstitial --Load Corona 'ads' library local ads   --=================================Ad listener============================================ --This listener is for Ads function adListener( event ) local msg = event.response -- just a quick debug message to check what response we got from the library --print("Message received from the ads library: ", msg)   if ( event.isError ) then -- attempt to fetch another ad print("---------------------ad error----------------------") elseif ( event.phase == "loaded" ) then -- an ad was preloaded print("---------------------ad is loaded and ready----------------------") DATA.adshown = false elseif ( event.phase == "shown" ) then -- the ad was viewed and closed print("---------------------ad shown----------------------") if ( event.type == "interstitial" ) then DATA.adshown = true end end end   --This function is for initialise Ads function adsLib:initialize() --print(" Corona initialize ads") ads = require "ads" ads\_appID = "ca-app-pub-xxxxxxxxxxxxxxxxx" ads\_appID\_interstitial = "ca-app-pub-xxxxxxxxxxxxx" ads.init( adsprovider, ads\_appID, adListener ) ads.init( adsprovider, ads\_appID\_interstitial, adListener ) end --This function is for unrequire the Ads library function adsLib:unRequire() --print(" Corona unrequire ads") package.loaded["ads"] = nil \_G["ads"] = nil end   --load the ad before showing function adsLib:loadAd ( adType ) --print("show ads") local adX, adY =0 , 0--\_H-80 --local deviceModel = if DATA.environment == "simulator" then -- no ads in simulator ads.load( "interstitial", { appId=ads\_appID\_interstitial, testMode=true } ) elseif DATA.environment =="Android" then ads.load( "interstitial", { appId=ads\_appID\_interstitial, testMode=false } ) end end   -- check if the ad was pre-loaded function adsLib:isLoaded ( adType ) if (ads.isLoaded( "interstitial" )) then return true else return false end end   -- Shows a specific type of ad function adsLib:showAd ( adType,place ) --print("show ads") local adX, adY =0 , 0--\_H-80 --local deviceModel = if DATA.environment == "simulator" then --print("no ads on simulator") if adType == "banner" then if place == "bottom" then adY = \_H-90 elseif place == "header" then adY = 0 end ads.show( adType, { x=adX, y=adY , appId=ads\_appID } ) elseif adType == "interstitial" then ads.show( adType, { appId=ads\_appID\_interstitial, testMode=false } ) end elseif DATA.environment =="Android" then if adType == "banner" then if place == "bottom" then adY = \_H-90 elseif place == "header" then adY = 0 end ads.show( adType, { x=adX, y=adY , appId=ads\_appID } ) elseif adType == "interstitial" then ads.show( adType, { appId=ads\_appID\_interstitial, testMode=false } ) end end end   --This function is for Hide Ads function adsLib:hideAd() --print("hide ads") if DATA.environment == "simulator" then --print("no ads on simulator") ads.hide() else ads.hide() end   end   return adsLib  

Your last suggestion makes me wonder if the ads.isLoaded function gets set to true when the ad starts loading, or when the ad is finished loading is ready.  The behavior of my app seems to suggest that maybe it gets set to true when the ad starts loading, but I would think that this would be counter-intuitive and not designed this way…  Can you comment on that? 

My advice is to put in some print statements and see whats going on, in particular in your listener function to see what all’s going on.  Make sure you’re printing out the values returned in that listener function.

You should also get a call back to your listener function when the ad has loaded.

Rob

I am also stuck there - since the ads library doesn’t work in the simulator…  I was unable to get the adb working on my Windows laptop, and I am stuck on a MacBook 2,1 which I do not think can get to Mountain Lion which is required for the right Xcode to run the iOS simulator.  At least that is what I read on another site…  

I will look more into it.  My forum searches didn’t find anything definitive on the versioning needed.  I will give the adb another shot as well…

Thank you for your help and for your time looking at this.  I will post an update if I ever find a way to get it solved/worked around.

any ideas???  any suggestions of things to try?

Hello @sonyayllc,

Which ad service/provider are you implementing?

Brent

AdMob v2 - the ads all show as intended, it is just the delay that is the problem.

Do you pre-load the interstitials?

Brent

Yes, I use that in the condition to determine if the adscene should be entered. I only show the ad once every few rounds, so if the count is reached, the ad is loaded. The next round checks if the ad is loaded before going to the adscene where the ads.show is called. The logic seems to check out, but when the adscene does load and calls the ad.show, the next scene starts to load before the ad appears… I am away from my computer but can post the code tomorrow if will help show the flow. Thanks for your help!

Hopefully this helps, these are the main pieces I have been working with.

Here is the adlistener:

--=================================Ad listener============================================ --This listener is for Ads function adListener( event ) local msg = event.response -- just a quick debug message to check what response we got from the library --print("Message received from the ads library: ", msg)   if ( event.isError ) then -- attempt to fetch another ad print("---------------------ad error----------------------") elseif ( event.phase == "loaded" ) then -- an ad was preloaded print("---------------------ad is loaded and ready----------------------") DATA.adshown = false elseif ( event.phase == "shown" ) then -- the ad was viewed and closed print("---------------------ad shown----------------------") if ( event.type == "interstitial" ) then DATA.adshown = true – this is flag being watched end end end

And this is the function that moves from the gamescreen to the adscreen or scorescreen depending on a count, if the ad is loaded, game modes, if the adfree option was purchased, etc.  It also loads the ad when appropriate.  It is a function called in the gamescreen.

--This function is for redirect user to score screen goToScoreScreen = function() audio.stop(gameBgChannel) adsLib:hideAd() for i=1,5 do if ansText[i].text == "" or tonumber(ansText[i].text) == nil then DATA.userAns[i] = "-" else DATA.userAns[i] = tonumber(ansText[i].text) end end   local options = { effect = "fromRight", time = 800, params ={screen="playerDataScreen"} } -- logic to go to the adScene or to the scoreScene -- check if ad is to be displayed if DATA.adPurchased == false and DATA.isRainbow == false then if DATA.displayAds == true then if DATA.counterforad == 2 then    -- number of rounds to skip before displaying ad, 2 for testing if ( adsLib:isLoaded("interstitial") ) then  -- check if the ad is loaded, go to adScene if ad is ready composer.gotoScene("adScreen", options ) else adsLib:loadAd( "interstitial" )     -- this is the ads.loadAd call composer.gotoScene("scoreScreen", options ) -- continue to score end else DATA.counterforad = DATA.counterforad + 1  -- count the round, go to score as normal composer.gotoScene("scoreScreen", options ) end end elseif DATA.isRainbow == true then composer.gotoScene("scoreScreen", options ) end end

And here is the adscreen which shows the ad and then show the scorescreen

gotoscoreScreen = function () composer.gotoScene("scoreScreen", options ) end   timerpause = function() gotoscoreScreen() end   adshowncheck = function(event) if DATA.adshown == true then DATA.adshown = false --adsLib:hideAd() timer.cancel(adtimer) composer.gotoScene("scoreScreen", options ) composer.removeScene( "adScreen" ) -- timer.cancel(adtimer) end end -- ------------------------------------------------------------------------------- -- "scene:create()" function scene:create( event ) local group = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. --print ("wait for ad to close")   adsLib:showAd( "interstitial", nil )  -- this calls the ads.showAd function in adsLib DATA.counterforad = 1    -- reset counter DATA.adcalled = true    --loop until ad is set as 'shown' adtimer = timer.performWithDelay(200,adshowncheck,0)   --timer.performWithDelay(3000,timerpause) --gotoscoreScreen()   end   -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc.   composer.removeHidden() end end

Hi @sonyayllc,

Unfortunately, I can’t fully diagnose this because you’re using the “adsLib” library, which is not something we control (nor am I familiar with its code or functionality). As a general piece of advice, I would suggest that you pre-load the ad as soon as it’s realistically possible, so you have it in the queue for when you need it. For example, load it as soon as the main scene shows, then show it when necessary. As noted in the docs, you can also use the “.isLoaded” call to make sure the ad is loaded and, if not, then you load it up.

Take care,

Brent

This is the adsLib - I understand that you don’t control it, but it isn’t a modification of the ads.* library from Corona, it is just a different location for calling the ads.* functions.  I am not sure why my developer did it this way… it is actually redundant in a way, or at least an extra step in the process.

local DATA = require("gameData") local adsLib = {} --==================================For Advertising ====================================== -- The name of the ad provider. local adsprovider = "admob" -- Your application ID local ads\_appID local ads\_appID\_interstitial --Load Corona 'ads' library local ads   --=================================Ad listener============================================ --This listener is for Ads function adListener( event ) local msg = event.response -- just a quick debug message to check what response we got from the library --print("Message received from the ads library: ", msg)   if ( event.isError ) then -- attempt to fetch another ad print("---------------------ad error----------------------") elseif ( event.phase == "loaded" ) then -- an ad was preloaded print("---------------------ad is loaded and ready----------------------") DATA.adshown = false elseif ( event.phase == "shown" ) then -- the ad was viewed and closed print("---------------------ad shown----------------------") if ( event.type == "interstitial" ) then DATA.adshown = true end end end   --This function is for initialise Ads function adsLib:initialize() --print(" Corona initialize ads") ads = require "ads" ads\_appID = "ca-app-pub-xxxxxxxxxxxxxxxxx" ads\_appID\_interstitial = "ca-app-pub-xxxxxxxxxxxxx" ads.init( adsprovider, ads\_appID, adListener ) ads.init( adsprovider, ads\_appID\_interstitial, adListener ) end --This function is for unrequire the Ads library function adsLib:unRequire() --print(" Corona unrequire ads") package.loaded["ads"] = nil \_G["ads"] = nil end   --load the ad before showing function adsLib:loadAd ( adType ) --print("show ads") local adX, adY =0 , 0--\_H-80 --local deviceModel = if DATA.environment == "simulator" then -- no ads in simulator ads.load( "interstitial", { appId=ads\_appID\_interstitial, testMode=true } ) elseif DATA.environment =="Android" then ads.load( "interstitial", { appId=ads\_appID\_interstitial, testMode=false } ) end end   -- check if the ad was pre-loaded function adsLib:isLoaded ( adType ) if (ads.isLoaded( "interstitial" )) then return true else return false end end   -- Shows a specific type of ad function adsLib:showAd ( adType,place ) --print("show ads") local adX, adY =0 , 0--\_H-80 --local deviceModel = if DATA.environment == "simulator" then --print("no ads on simulator") if adType == "banner" then if place == "bottom" then adY = \_H-90 elseif place == "header" then adY = 0 end ads.show( adType, { x=adX, y=adY , appId=ads\_appID } ) elseif adType == "interstitial" then ads.show( adType, { appId=ads\_appID\_interstitial, testMode=false } ) end elseif DATA.environment =="Android" then if adType == "banner" then if place == "bottom" then adY = \_H-90 elseif place == "header" then adY = 0 end ads.show( adType, { x=adX, y=adY , appId=ads\_appID } ) elseif adType == "interstitial" then ads.show( adType, { appId=ads\_appID\_interstitial, testMode=false } ) end end end   --This function is for Hide Ads function adsLib:hideAd() --print("hide ads") if DATA.environment == "simulator" then --print("no ads on simulator") ads.hide() else ads.hide() end   end   return adsLib  

Your last suggestion makes me wonder if the ads.isLoaded function gets set to true when the ad starts loading, or when the ad is finished loading is ready.  The behavior of my app seems to suggest that maybe it gets set to true when the ad starts loading, but I would think that this would be counter-intuitive and not designed this way…  Can you comment on that? 

My advice is to put in some print statements and see whats going on, in particular in your listener function to see what all’s going on.  Make sure you’re printing out the values returned in that listener function.

You should also get a call back to your listener function when the ad has loaded.

Rob