What is callback() in modules?

Below is the code found in the lib.appodeal module of lama_chef sample

 local function adListener( event ) if ( event.phase == "init" ) then -- Successful initialization print( event.isError ) appodeal.load( "banner" ) -- appodeal.load( "interstitial" ) appodeal.load( "rewardedVideo" ) elseif (event.phase=="playbackEnded") then if M.callback then M.callback() M.callback=nil end elseif (event.phase=="failed") then end end appodeal.init( adListener, { appKey=appKey, testMode=false, bannerAnimation = true, hasUserConsent = true, supportedAdTypes = {"interstitial", "banner", "rewardedVideo"} } )

What is the function of M.callback() here??

If we call init function  (which is available in this module) from  some other module,how to know if video play completed??

You didn’t provide the full context of what M.init() does, but going from memory, there is a developer made module that handles setting up Appodeal. I believe that in calling the modules initialization function, you can specify a callback listener. This function is stored in M.callback and if it exists, when a rewardVideo generates a complete event (i.e. event.phase == “playbackEnded”), if M.callback has been populated, that function is called. This is how you can write your own function to execute after a video play is completed.

Rob

It is a bit complicated to understand

M.init() is below

function M:init() local gdprResult = system.getPreference( "app", "result\_gdpr", "boolean" ) local hasUserConsent = false if gdprResult ~= nil then if gdprResult == true then hasUserConsent = gdprResult end end local appKey = nil if platform == "android" then appKey="d1379110fd0c24f53396afe99ce7d3bb699a29edc7cc9cb4" elseif platform == "ios" then appKey = "d1379110fd0c24f53396afe99ce7d3bb699a29edc7cc9cb4" end local function adListener( event ) if ( event.phase == "init" ) then -- Successful initialization print( event.isError ) appodeal.load( "banner" ) -- appodeal.load( "interstitial" ) appodeal.load( "rewardedVideo" ) elseif (event.phase=="playbackEnded") then if M.callback then M.callback() M.callback=nil end elseif (event.phase=="failed") then end end appodeal.init( adListener, { appKey=appKey, testMode=false, bannerAnimation = true, hasUserConsent = true, supportedAdTypes = {"interstitial", "banner", "rewardedVideo"} } )

Below is the function that calls the ad_show function

 continueButton.y = 145 function continueButton:touch(e) if e.phase=="began" then if \_ads then \_ads.callback = function() local event = { name="target", phase="continue", target=target } target:dispatchEvent( event ) group:destroy() end if \_ads:isLoaded("rewardedVideo") then \_ads:showReward() else showMessage("please try again later") end end end return true end

Here how playbackEnded is detected and game continiues?

So basically the system works like this (in a very generic way)

  1. Create a function that handles events from the ad provider

  2. Initialize the plugin telling the .init() method the address of the function that handles the events (listener function).

  3. After the plugin initializes, load the ad.

  4. Show the ad when the user asks to see it.

  5. When the ad is complete, your listener function that you created in step 1 gets called with an event.phase == “playbackEnded”.

  6. In that listener function, you look for that event.phase and write code to process the reward for the user.

Now in Lama Chef, the author decided to make a module to do all of that work but he didn’t want to write the code to process the reward inside that listener function. This can be good programming style because you don’t want one function having too much code can make the function hard to maintain. He chose to pass an additional function reference in (the callback function) to do the work. This changes the steps above to be more like:

  1. Create a callback function that processes the reward.

  2. Create a function that handles events from the ad provider

2.1  If the callback function exists, call it

  1. Initialize the plugin telling the .init() method the address of the function that handles the events (listener function).

  2. Tell the Ad Module what the callback function is

  3. After the plugin initializes, load the ad.

  4. Show the ad when the user asks to see it.

  5. When the ad is complete, your listener function that you created in step 1 gets called with an event.phase == “playbackEnded”.

  6. In that listener function, you look for that event.phase and write code to process the reward for the user.

You can learn more about ad processing in your “Implementing Ads” tutorial:

http://docs.coronalabs.com/tutorial/basics/ads/index.html

Rob

Thanks

Below is my  main.lua

 local appodeal = require("plugin.appodeal") local function adListener(event) if event.phase=="playbackEnded" then print("givereward") end end appodeal.init( adListener, { appKey=appKey, testMode=false, bannerAnimation = true, hasUserConsent = gdprResult, } ) composer.gotoScene("game")

And below is game.lua

local appodeal=require"appodeal" if appodeal.isLoaded("rewardedVideo") then appodeal.show("rewardedVideo") end

Since the listener is in main.lua, I don’t know how to access it from game.lua ( so that I can know if video was completed)

If I put the initialization code and listener in game.lua ,it will be called very often( during every “restart” or “start” of the level)

If I put the initialization code and listener in main.lua,I cannot know If video has completed playing

So should I initialize the appodeal.init() from game.lua every single time or are there any other ways to do it?

If I call a function of game.lua from main.lua to indicate that the video was completed,will it work?

If I put the initialization code and listener in game.lua 

Please read (or re-read) this: http://docs.coronalabs.com/tutorial/basics/ads/index.html

Then read this: https://coronalabs.com/blog/2018/10/02/monetization-best-practices-and-a-new-ad-tutorial/

Absolutely do not initialize ads in game.lua.

Where are you preloading the ad (calling .load() )?

Absolutely do not force the user to view a rewardedVideo. This needs to be on a button where you ask them if they want to view the rewarded video and only show the ad if they say yes. It has to be the app user’s choice.

As far as how do you reward the video, that’s going to be really hard for anyone to answer because you have told us nothing about your in-game economy?  What does the player get for viewing the video? If you’re giving them coins, the answer will be different than if you let them continue to the next level after losing or causing them to restart.

In generic terms, if you need to know if the reward view was complete in game.lua, then you can in game.lua do:

function scene:handleRewardedVideo( amount )     -- put your code here to do whatever you need to do end

Then in your listener function in main.lua, do something like:

local function appodealListener( event ) print("\*\*\* APPODEAL \*\*\*", event.phase) if ( event.phase == "init" ) then -- Successful initialization print( event.isError ) elseif event.phase == "playbackEnded" and event.data then local amount = event.data.amount local sceneName = composer.getSceneName("current") if sceneName == "game" then local scene = composer.getScene( scene ) scene:handleRewardedVideo( amount ) end end end

This basically grabs the current composer scene info and gets a reference to the scene’s scene object. Since you have created a function in game.lua that’s now a method of the scene object, you can call that function from the listener function.

Rob

Thanks rob…

Thanks for explaining very clearly… :D  :D  :smiley:

You didn’t provide the full context of what M.init() does, but going from memory, there is a developer made module that handles setting up Appodeal. I believe that in calling the modules initialization function, you can specify a callback listener. This function is stored in M.callback and if it exists, when a rewardVideo generates a complete event (i.e. event.phase == “playbackEnded”), if M.callback has been populated, that function is called. This is how you can write your own function to execute after a video play is completed.

Rob

It is a bit complicated to understand

M.init() is below

function M:init() local gdprResult = system.getPreference( "app", "result\_gdpr", "boolean" ) local hasUserConsent = false if gdprResult ~= nil then if gdprResult == true then hasUserConsent = gdprResult end end local appKey = nil if platform == "android" then appKey="d1379110fd0c24f53396afe99ce7d3bb699a29edc7cc9cb4" elseif platform == "ios" then appKey = "d1379110fd0c24f53396afe99ce7d3bb699a29edc7cc9cb4" end local function adListener( event ) if ( event.phase == "init" ) then -- Successful initialization print( event.isError ) appodeal.load( "banner" ) -- appodeal.load( "interstitial" ) appodeal.load( "rewardedVideo" ) elseif (event.phase=="playbackEnded") then if M.callback then M.callback() M.callback=nil end elseif (event.phase=="failed") then end end appodeal.init( adListener, { appKey=appKey, testMode=false, bannerAnimation = true, hasUserConsent = true, supportedAdTypes = {"interstitial", "banner", "rewardedVideo"} } )

Below is the function that calls the ad_show function

 continueButton.y = 145 function continueButton:touch(e) if e.phase=="began" then if \_ads then \_ads.callback = function() local event = { name="target", phase="continue", target=target } target:dispatchEvent( event ) group:destroy() end if \_ads:isLoaded("rewardedVideo") then \_ads:showReward() else showMessage("please try again later") end end end return true end

Here how playbackEnded is detected and game continiues?

So basically the system works like this (in a very generic way)

  1. Create a function that handles events from the ad provider

  2. Initialize the plugin telling the .init() method the address of the function that handles the events (listener function).

  3. After the plugin initializes, load the ad.

  4. Show the ad when the user asks to see it.

  5. When the ad is complete, your listener function that you created in step 1 gets called with an event.phase == “playbackEnded”.

  6. In that listener function, you look for that event.phase and write code to process the reward for the user.

Now in Lama Chef, the author decided to make a module to do all of that work but he didn’t want to write the code to process the reward inside that listener function. This can be good programming style because you don’t want one function having too much code can make the function hard to maintain. He chose to pass an additional function reference in (the callback function) to do the work. This changes the steps above to be more like:

  1. Create a callback function that processes the reward.

  2. Create a function that handles events from the ad provider

2.1  If the callback function exists, call it

  1. Initialize the plugin telling the .init() method the address of the function that handles the events (listener function).

  2. Tell the Ad Module what the callback function is

  3. After the plugin initializes, load the ad.

  4. Show the ad when the user asks to see it.

  5. When the ad is complete, your listener function that you created in step 1 gets called with an event.phase == “playbackEnded”.

  6. In that listener function, you look for that event.phase and write code to process the reward for the user.

You can learn more about ad processing in your “Implementing Ads” tutorial:

http://docs.coronalabs.com/tutorial/basics/ads/index.html

Rob

Thanks

Below is my  main.lua

 local appodeal = require("plugin.appodeal") local function adListener(event) if event.phase=="playbackEnded" then print("givereward") end end appodeal.init( adListener, { appKey=appKey, testMode=false, bannerAnimation = true, hasUserConsent = gdprResult, } ) composer.gotoScene("game")

And below is game.lua

local appodeal=require"appodeal" if appodeal.isLoaded("rewardedVideo") then appodeal.show("rewardedVideo") end

Since the listener is in main.lua, I don’t know how to access it from game.lua ( so that I can know if video was completed)

If I put the initialization code and listener in game.lua ,it will be called very often( during every “restart” or “start” of the level)

If I put the initialization code and listener in main.lua,I cannot know If video has completed playing

So should I initialize the appodeal.init() from game.lua every single time or are there any other ways to do it?

If I call a function of game.lua from main.lua to indicate that the video was completed,will it work?

If I put the initialization code and listener in game.lua 

Please read (or re-read) this: http://docs.coronalabs.com/tutorial/basics/ads/index.html

Then read this: https://coronalabs.com/blog/2018/10/02/monetization-best-practices-and-a-new-ad-tutorial/

Absolutely do not initialize ads in game.lua.

Where are you preloading the ad (calling .load() )?

Absolutely do not force the user to view a rewardedVideo. This needs to be on a button where you ask them if they want to view the rewarded video and only show the ad if they say yes. It has to be the app user’s choice.

As far as how do you reward the video, that’s going to be really hard for anyone to answer because you have told us nothing about your in-game economy?  What does the player get for viewing the video? If you’re giving them coins, the answer will be different than if you let them continue to the next level after losing or causing them to restart.

In generic terms, if you need to know if the reward view was complete in game.lua, then you can in game.lua do:

function scene:handleRewardedVideo( amount )     -- put your code here to do whatever you need to do end

Then in your listener function in main.lua, do something like:

local function appodealListener( event ) print("\*\*\* APPODEAL \*\*\*", event.phase) if ( event.phase == "init" ) then -- Successful initialization print( event.isError ) elseif event.phase == "playbackEnded" and event.data then local amount = event.data.amount local sceneName = composer.getSceneName("current") if sceneName == "game" then local scene = composer.getScene( scene ) scene:handleRewardedVideo( amount ) end end end

This basically grabs the current composer scene info and gets a reference to the scene’s scene object. Since you have created a function in game.lua that’s now a method of the scene object, you can call that function from the listener function.

Rob

Thanks rob…

Thanks for explaining very clearly… :D  :D  :smiley: