Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

How to use the Vungle listener? Does it work?
Started by LairdGames Jul 24 2013 04:53 PM

94 replies to this topic
[TOPIC CONTROLS]
Page 2 of 4 1 2 3 4
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#26

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

If you want Chartboost then READ_PHONE_STATE *must* be removed as per their instructions.

Vungle doesn't need it. RevMob *claim* they need it, however during my testing it looks like it's working without it.



[TOPIC: post.html]
#27

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

can give a pointer on how to switch between ads?



[TOPIC: post.html]
#28

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I've been able to integrate Chartboost (and get ads) for all stores Apple, Google Play and Amazon.

 

 

I can't really post any code since it wouldn't make much sense to anybody else. It's highly modularised with dependencies all over the place...

 

I switch between the different ad-platforms by using the delegates for each ad-platform to determine the success/failure of each request. Each ad platform have their own delegates that are explained in their respective documentation and sample apps.

 

I have two strategies for my ads
1) App startup ads

During app startup I use Chartboost. If no Charboost ads are found I show a RevMob fullscreen ad. I control this by using the Chartboost delegates.

 

2) In-between game ads

Apple/GooglePlay: Here I show a Vungle ad first. If no vungle ads are available I try to show a Chartboost ad, and if that fails it drops down to a Revmob Popup.

 

Amazon: Since Vungle isn't available for this platform I just try Chartboost first and then a RevMob Popup.



[TOPIC: post.html]
#29

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

Thank you for your help. And sorry for asking too many questions.



[TOPIC: post.html]
#30

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

No problem! No need to apologize... asking questions is the way we learn. If you run in to any specific problems please feel free to ask more :-)

[TOPIC: post.html]
#31

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

I am doing pretty much what Ingemar is doing. Same here, the code is all over the place but here a quick look at my code:

 

-- Listener for Vungle
 
function VungleListener( event )
         
if event.type == "adStart" and event.isError then
native.setActivityIndicator(true)
chartboost_show_ad()
end
end
 
-- If Vungle fail then I call Chartboost and here (part of ) of the listener for Chartboost calling Revmob
 
didFailToLoadInterstitial = function(location)print("Chartboost: didFailToLoadInterstitial " .. location); native.setActivityIndicator(false);showRevmob();  return end,........
 

 

If Revmob fail then I simply turn off the native activity indicator (you notice I start the indicator at the same time I call an ad network so to mask the IU during the wait to get the ad) and call it a day. Later I may show my own made app after I get two apps in the store...

 

I do show Revmob at app startup/resume. And use the strategy above only for end of gameplay.

 

Not sure if people are using the code as above but if you need to release an app in two days and it is for IOS, I will strongly suggest to take time to test all this stuff and simply release one ad network for now. If it is for Android, then you can of course fix basically on the fly since you do not need Apple approval.

 

Hope this help.

 

Mo



[TOPIC: post.html]
#32

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

@ingemar thank you so much.

 

@Mo that's what I was looking for. Infact, I was wondering if I could implement the code in a similar fashion and I saw your reply. Also chartboost support has offered a solution. So now m good with Vungle+chartboost+tapfortap.

 

Thanks a lot you guys are amazing.



[TOPIC: post.html]
#33

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Awesome! Let us know how it worked out. Since I planning on releasing an update to my Space Command using Vungle/Chartboost/Revmob on IOS, I will need more time to test that they all work nicely with each other. Of course because it takes so long for Apple review...

 

Good luck on your app with all those goodies ad networks :)

 

Mo



[TOPIC: post.html]
#34

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

Mo,

 

You can use CoronaProvider.ads.vungle.isAdAvailable() to check if an ad is cached, its way better then calling chartboost in case of vungle ad failure. Vungle tries to load the ad if it fails the first time. You can use the above function to check if there's any ad to show and then show vungle else show chartboost.



[TOPIC: post.html]
#35

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

THANKS! I will try CoronaProvider.ads.vungle.isAdAvailable() then as

 

if CoronaProvider.ads.vungle.isAdAvailable() ~= true then showChartboost()  end

 

I appreciate the tip. The main issue is that since my app is still in testing mode, Vungle is et to test mode too so I rarely miss a video so it is hard to test failure (so it switch to Chartboost) I guess a week before release, I will ask Vungle to switch to "live" so I can really switch real life conditions.

 

Thanks again,

 

Mo



[TOPIC: post.html]
#36

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

@Mo

You can switch to Live yourself (just click the 'Active' button in the dashboard), however once you do you can't switch back to Testing mode...



[TOPIC: post.html]
#37

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

This one worked once now throwing an error, i don't know whats wrong here. http://docs.coronalabs.com/daily/plugin/vungle/index.html

 

I'll just try to figure out and let you know.



[TOPIC: post.html]
#38

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

[TOPIC: post.html]
#39

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

This is what m doing

 

function M.show_vungle_ad()
	
		if M.ads.isAdAvailable() then
			M.ads.show( "interstitial", { isBackButtonEnabled = true } )
		
		else
	
			M.chartboost_show_ad()
		end
	end
	
	function M.functionAdListener()
		if event.type == "adStart" and event.isError then
			print("Vungle Error: ",isError)
		end
	end
	
	function M.chartboost_show_more_ad()
		if M.cb.hasCachedMoreApps() then
			local msg = "Chartboost: Loading More Apps From Cache"
		end
		print(msg)
		M.cb.showMoreApps()
		return true
	end
	
	function M.chartboost_show_ad()
		if M.cb.hasCachedInterstitial() then
			local msg = "Chartboost: Loading Interstitial From Cache"
			print(msg)
			M.cb.showInterstitial()
			
		else
			
			M.tapfortap.showInterstitial()
		
		end
		return true
	end

btw I've put them all in a separate lua file just to avoid globals.



[TOPIC: post.html]
#40

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

@Ingemar: That's true! I will do that and avoid clicking on ad :)

 

@Sagarpawaskar: THANKS! That's a great piece of code! I see what you are doing. You have something like a table M and return M. Then in any module you need to show an ad, you require that lua file and then call show_vungle_ad()

Correct?

 

 

That's very cool :) I am wondering where you put all those ad networks initialization codes? I will assume main.lua?

 

In any event, thank you so much for sharing. I appreciate that. I will try to emulate your way.

 

Mo



[TOPIC: post.html]
#41

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

I can't see anything wrong after a quick read.

 

Here's my adnetwork module I use. It has references to other modules, but I hope you'll be able to make some sense out of it.

 

One tip: My module temporarily fixes the Chartboost problem of not filling the background of devices with wider and taller displays (iPhone5//iPad) when using letterbox mode (you shouldn't mess with the width/height settings in config.lua as it will mess up the aspect ratio of the screen which will affect any splash screens you have).

 

Here's my module:

-- adnetworks.lua
-- created: 2013-07-27
--
-- Ingemar Bergmark
-- www.swipeware.com

local M = {};

local app = require("appglobals");
local directives = require("directives");
local iap = require("inapp");
local ads = require("ads");

local flags = app.getFlags();
local settings = app.getSettings();
local screen = app.getScreen();

M.isActive = false;				-- true if any ad network is showing an ad
M.adTapped = false;				-- used to prevent new ad from showing when coming back from a tapped ad

-- ------------------------------------------------------------------------
-- Vungle
-- ------------------------------------------------------------------------
local VUNGLE_APPID = {
	Apple	= {ID = "xxx"},
	Google	= {ID = "com.swipeware.freemium.appname"}
}

local vungleListener = function(event)
	local eventType = event.type;
	local isError = event.isError;
	
	if (eventType == "adStart") then
		if (isError) then
			M.showRevmobPopup();
		else
			audio.pause(flags.chatterChannel);
			M.isActive = true;
			flags.cancelAllTouches();
		end
		
	elseif (eventType == "adEnd") then
		audio.resume(flags.chatterChannel);
		M.isActive = false;
	end
end

local vungleInit = function()
	if (directives.STORE ~= "Amazon") then
		ads.init("vungle", VUNGLE_APPID[directives.STORE].ID, vungleListener);	
		
		M.showVungleFullscreen = function()
			if (not M.isActive) then
				ads.show("interstitial");
			else
				print("vungle: ad is active")
			end
		end
	end
end

M.isVungleAvailable = function()
	if (type(ads.isAdAvailable) == "function") then
		return ads.isAdAvailable();
	end
	
	return false;
end


-- ------------------------------------------------------------------------
-- revmob
-- ------------------------------------------------------------------------
local REVMOB_APPID = {
	Apple	= {ID = "xxx"},
	Google	= {ID = "yyy"},
	Amazon	= {ID = "zzz"}
}

local revmob = nil;					-- RebMob handle
local revmobFullScreenAd = nil;		-- revmob fullscreen ad
local revmobPopupAd = nil;			-- revmob popup ad
local revmobAndroidKey = "Google"	-- revmob key for android (must be defined even on iOS builds)
local revmobFallback;				-- fallback popup/full in case chartboost ad not available

if (directives.TARGET == "Android") then
	revmobAndroidKey = directives.STORE;		
end
	
local showRevmobAd = function(adType)
	M.isActive = true;
	flags.cancelAllTouches();

	if (adType == "fullscreen") then
		revmobFullScreenAd:show();
	else -- popup
		--revmobPopupAd:show();
	end
end

local hideRevmobAd = function()
	if (revmobFullScreenAd) then
		M.isActive = false;
		revmobFullScreenAd:hide();
		revmobFullScreenAd = nil;
	end
	
	if (revmobPopupAd) then 
		M.isActive = false;
		revmobPopupAd:hide();
		revmobPopupAd = nil;
	end
end

local revmobListener = function(event)
	local eventType = event.type;
	local adType = event.ad;

	if (eventType == "adReceived") then
		if (flags.canShowAds()) then
			flags.pauseGame();
			showRevmobAd(adType);
		else
			hideRevmobAd();
		end
		
	elseif (eventType == "adClicked") then
		M.adTapped = true;
		M.isActive = false;

	elseif (eventType == "adClosed") then
		hideRevmobAd();
	
	elseif (eventType == "adNotReceived") then
		hideRevmobAd();
	end
end

local revmobInit = function()
	revmob = require("revmob");

	local locationHandler = function(event)
		-- Check for error (user may have turned off Location Services)
		if (event.errorCode) then
			print("Location error: "..tostring(event.errorMessage));
		else
			revmob.setUserLocationLatitude(event.latitude);
			revmob.setUserLocationLongitude(event.longitude);
			revmob.setUserLocationAccuracy(event.accuracy);
		end

		Runtime:removeEventListener("location", locationHandler);
	end
	
	local revmobIDs = {["Android"] = REVMOB_APPID[revmobAndroidKey].ID, ["iPhone OS"] = REVMOB_APPID.Apple.ID};
	
	if (flags.TEST_MODE) then
		revmob.startSession(revmobIDs);
		revmob.setTestingMode(revmob.TEST_WITH_ADS);
		revmob.printEnvironmentInformation(revmobIDs);
	else
		revmob.startSession(revmobIDs);
		revmob.printEnvironmentInformation(revmobIDs);
	end
	
	Runtime:addEventListener("location", locationHandler);
	
	M.showRevmobFullscreen = function()
		if (not M.isActive) then
			revmobFullScreenAd = revmob.createFullscreen(revmobListener);
		else
			print("revmob fullscreen: ad is active")
		end
	end

	M.showRevmobPopup = function()
		if (not M.isActive) then
			revmobPopupAd = revmob.showPopup(revmobListener);
		else
			print("revmob popup: ad is active")
		end
	end
end

-- ------------------------------------------------------------------------
-- ChartBoost
-- ------------------------------------------------------------------------
local CHARTBOOST_APPID = {
	Apple	= {ID = "xxx", SIG = "xxx2"},
	Google	= {ID = "yyy", SIG = "yyy2"},
	Amazon	= {ID = "zzz", SIG = "zzz2"}
}

local chartboost = nil;			-- Chartboost handle
local overlay1 = nil;			-- temporary overlays for chartboost background
local overlay2 = nil;		

local removeOverlays = function()
	local destroyOverlay = function(object)
		object:removeEventListener("touch", object);
		object:removeEventListener("tap", object);
		object:removeSelf();
	end
	
	if (overlay1) then destroyOverlay(overlay1) end;
	if (overlay2) then destroyOverlay(overlay2) end;
	
	overlay1 = nil;
	overlay2 = nil;
end

local createOverlays = function()
	local configOverlay = function(object)
		function object:touch(event)
			return true;
		end
		
		function object:tap(event)
			return true;
		end
		
		object:setFillColor(0, 160);
		object:addEventListener("touch", object);
		object:addEventListener("tap", object);
		object:toFront();
		transition.from(object, {time=600, alpha=0});
	end
	
	removeOverlays(); -- remove old overlays in case they are still there

	if (screen.left < 0) then
		overlay1 = display.newRect(screen.left, screen.top, math.abs(screen.left), screen.height);
		overlay2 = display.newRect(screen.right+screen.left, screen.top, math.abs(screen.left), screen.height);
	end
	
	if (screen.top < 0) then
		overlay1 = display.newRect(screen.left, screen.top, screen.width, math.abs(screen.top));
		overlay2 = display.newRect(screen.left, screen.bottom+screen.top, screen.width, math.abs(screen.top));
	end
		
	if (overlay1) then configOverlay(overlay1) end;
	if (overlay2) then configOverlay(overlay2) end;
end

local chartboostDelegate = {
	shouldRequestInterstitial = function(location)
		return true;
	end,
	
	shouldRequestInterstitialsInFirstSession = function() 
		return true; 
	end,
	
    shouldDisplayInterstitial = function(location) 
		if (flags.canShowAds()) then
			createOverlays();
			flags.pauseGame();
			flags.cancelAllTouches();
			M.isActive = true;
			return true;
		else
			return false; --ignore ad
		end
	end,
	
	didDismissInterstitial = function(location)
		timer.performWithDelay(600, removeOverlays);
		M.isActive = false;
		return;
	end,
	
	didCloseInterstitial = function(location)
		M.isActive = false;
		return;
	end,
	
    didFailToLoadInterstitial = function(location) 
		M.isActive = false;
		if (revmobFallback == "popup") then
			M.showRevmobPopup();
		else
			M.showRevmobFullscreen();
		end
		return; 
	end,
		
    didClickInterstitial = function(location) 
		M.adTapped = true; 
		M.isActive = false;
		return;
	end
}

local chartboostInit = function()
	chartboost = require("ChartboostSDK.chartboost");
	
	flags.bundleid = "com.swipeware.freemium.appname";
	
	chartboost.create{
		appId = CHARTBOOST_APPID[directives.STORE].ID,
		appSignature = CHARTBOOST_APPID[directives.STORE].SIG,
		delegate = chartboostDelegate,
		appVersion = settings.version,
		appBundle = flags.bundleid
	};
		
	M.showChartboostFullscreen = function(fallback)
		revmobFallback = fallback;
		if (not M.isActive) then
			chartboost.showInterstitial();
		else
			print("chartboost: ad is active");
		end
	end
end

M.startChartboostSession = function()
	chartboost.startSession();
end

-- ------------------------------------------------------------------------

M.hideAds = function()
	hideRevmobAd();
end

if (not iap.isBought()) then
	revmobInit(); 
	vungleInit();
	chartboostInit();
end	

return M;



[TOPIC: post.html]
#42

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

@Mo I initialize the ad networks in mainmenu, that way I have a window to cache ads if they fail initially. So if a user returns to menu I can re-cache them. And yes I use M table to return.



[TOPIC: post.html]
#43

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

Fantastic share i am having a great time looking into it. My code is some complex because I basically put everything in main.lua! I really like you guys modular approach. Naomi suggested that as well but did not get a chance to look into it. Thanks guys, that really, really help.

 

Mo 

 

ps: I did switch to "live" mode. It is so much easier to test the failures of not showing an ad! Thanks.



[TOPIC: post.html]
#44

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

@ingemar you were right, your code is quite complicated. With less time, I wouldn't do all that. But that's a good piece, thank you!!



[TOPIC: post.html]
#45

LairdGames

[GLOBAL: userInfoPane.html]
LairdGames
  • Contributor

  • 969 posts
  • Corona SDK

@Sagarpawaskar Cool! That make sense.

 

Thanks.

 

Mo



[TOPIC: post.html]
#46

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

@Mo glad you like that approach.

 

@ingemar I was wondering why do you check (type(ads.isAdAvailable)==function) for a function?



[TOPIC: post.html]
#47

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

@sagarpawaskar

I do that so that I don't get a runtime error when running in the Corona Simulator.



[TOPIC: post.html]
#48

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

@ingemar attempt to call ads.isAdAvailable() a nil value? I'm getting this error... If I get this to work, there's nothing else I've to look into.



[TOPIC: post.html]
#49

ingemar

[GLOBAL: userInfoPane.html]
ingemar
  • Corona Geek

  • 2,733 posts
  • Enterprise

If you test for it being a function before calling it (as I do) you'll get around this :-).

 

However you should only run in to this problem on the Simulator. A device should have this function if the plugin has been able to initialize properly...



[TOPIC: post.html]
#50

sagarpawaskar

[GLOBAL: userInfoPane.html]
sagarpawaskar
  • Enthusiast

  • 33 posts
  • Corona SDK

all good, thanks @ingemar that worked , will test this app once on the device.




[topic_controls]
Page 2 of 4 1 2 3 4
 
[/topic_controls]