Do I need to set the READ_PHONE_STATE enabled for vungle or admob on android? I read this on another post, but charboost needs that disabled, how do you deal with this?
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.
can give a pointer on how to switch between ads?
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
- 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.
- 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.
Thank you for your help. And sorry for asking too many questions.
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
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:
[lua]
– 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,…
[/lua]
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
@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.
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
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.
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
@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…
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.
@ingemar Is there anything m missing out http://docs.coronalabs.com/daily/plugin/vungle/isAdAvailable.html
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.
@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
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;
@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.
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.
@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!!