Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

What is callback() in modules?
Started by DevilDev Oct 01 2018 04:32 AM

6 replies to this topic
callback lama chef sample appodeal rewarded video

Best Answer Rob Miracle , 04 October 2018 - 06:39 AM

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

[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

DevilDev

[GLOBAL: userInfoPane.html]
DevilDev
  • Enthusiast

  • 59 posts
  • Corona SDK

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??



[TOPIC: post.html]
#2

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,970 posts
  • Corona Staff

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


  • DevilDev likes this

[TOPIC: post.html]
#3

DevilDev

[GLOBAL: userInfoPane.html]
DevilDev
  • Enthusiast

  • 59 posts
  • Corona SDK

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?



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,970 posts
  • Corona Staff

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

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

4. Tell the Ad Module what the callback function is

5. After the plugin initializes, load the ad.

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

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

8. 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



[TOPIC: post.html]
#5

DevilDev

[GLOBAL: userInfoPane.html]
DevilDev
  • Enthusiast

  • 59 posts
  • Corona SDK

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 



[TOPIC: post.html]
#6

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,970 posts
  • Corona Staff

  Best Answer

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



[TOPIC: post.html]
#7

DevilDev

[GLOBAL: userInfoPane.html]
DevilDev
  • Enthusiast

  • 59 posts
  • Corona SDK

Thanks rob...

Thanks for explaining very clearly.. :D  :D  :D




[topic_controls]
[/topic_controls]

Also tagged with one or more of these keywords: callback, lama chef sample, appodeal, rewarded video