I'm trying to reward a user for watching a video with AdMob. Although I couldn't find any tutorial on the subject, I found these two classes in the documentation:
GADRewardBasedVideoAd
GADRewardBasedVideoAdDelegate
I've set up the display of a GADRewardBasedVideoAd with the following View Controller code:
class MarketController: UIViewController, GADRewardBasedVideoAdDelegate {
override func viewDidLoad() {
super.viewDidLoad()
GADRewardBasedVideoAd.sharedInstance().delegate = self
let request = GADRequest()
// Requests test ads on test devices.
request.testDevices = ["2077ef9a63d2b398840261c8221a0c9b"]
GADRewardBasedVideoAd.sharedInstance().loadRequest(request, withAdUnitID: "ca-app-pub-3940256099942544/4411468910")
}
// MARK: Daily Reward Button Delegate
#IBAction func playVideoClicked() {
if GADRewardBasedVideoAd.sharedInstance().ready {
GADRewardBasedVideoAd.sharedInstance().presentFromRootViewController(self)
}
}
// MARK: GADRewardBasedVideoAdDelegate
func rewardBasedVideoAdDidStartPlaying(rewardBasedVideoAd: GADRewardBasedVideoAd!) {
MediaPlayer.pauseBackgroundMusic()
print("Reward Video: Started")
}
func rewardBasedVideoAdDidClose(rewardBasedVideoAd: GADRewardBasedVideoAd!) {
MediaPlayer.startBackgroundMusic()
requestLoadAd()
print("Reward Video: Complete")
}
func rewardBasedVideoAdWillLeaveApplication(rewardBasedVideoAd: GADRewardBasedVideoAd!) {
requestLoadAd()
print("Reward Video: Will leave application")
}
}
When I press the button to trigger the code in the "playVideoClicked" function, I just see a regular test interstitial (no video) and the "rewardBasedVideoDidStartPlaying" function never gets called. When I close the interstitial the "rewardBasedVideoAdDidClose" function is called, though. Does this mean I did something wrong, or does AdMob just not display test videos?
Also, how do I configure this ad as a Reward Video in the AdMob developer console?
Change request.testDevices = ["2077ef9a63d2b398840261c8221a0c9b"] to request.testDevices = [kGADSimulatorID] and it should be working.
Related
I've launched an iOS app, but I am having problems loading rewarded video ads using the Google Mobile Ads SDK.
When a player clicks the button to see a video ad, the player is shown a video very few times. Most of the time, the user is shown an error of Admob being unable to fill the request:
Error Domain=com.google.ads Code=1 "Request Error: No ad to show."
Sometimes it will take them several clicks before getting one, and sometimes they just can't get one no matter how many clicks. This issue happens more with my rewarded videos, but it also happens with my banner ad. Sometimes Google is unable to provide me with a banner ad. Does anyone know why this is not working?
My code for ads:
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
let scene = MainMenu(view.bounds.size, self, nil)
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
GADRewardBasedVideoAd.sharedInstance().delegate = self
GADRewardBasedVideoAd.sharedInstance().load(getRequest(),
withAdUnitID: rewardAdId)
// In this case, we instantiate the banner with desired ad size.
if GameViewController.bannerView == nil {
GameViewController.bannerView = GADBannerView(adSize: kGADAdSizeBanner)
GameViewController.bannerView.adUnitID = bannerId
GameViewController.bannerView.rootViewController = self
GameViewController.bannerView.load(getRequest())
GameViewController.bannerView.isHidden = true
addBannerViewToView(GameViewController.bannerView)
}
authenticateLocalPlayer()
QuestManager().checkForRefresh()
}
}
public func getRequest() -> GADRequest {
let request = GADRequest()
return request
}
public func displayRewardedVideo() {
if GADRewardBasedVideoAd.sharedInstance().isReady {
GADRewardBasedVideoAd.sharedInstance().present(fromRootViewController: self)
} else {
GameViewController.loadVideo()
}
}
public static func loadVideo(){
if !GADRewardBasedVideoAd.sharedInstance().isReady {
GADRewardBasedVideoAd.sharedInstance().load(GADRequest(),
withAdUnitID: rewardAdId)
}
}
func rewardBasedVideoAdDidClose(_ rewardBasedVideoAd: GADRewardBasedVideoAd) {
GADRewardBasedVideoAd.sharedInstance().load(getRequest(),
withAdUnitID: rewardAdId)
if let scene = gameScene {
scene.audioManager.unmmute()
}
print("Video did close")
}
I am currently working at a certain company that provides tons of free mobile applications with Admob as a freelancer, so I'm quite adept with it.
Anyways, what I've learned from the manager of my company (they also have a Google Admob consultant there), is that the ad to be shown in an app can be dependent to the country that the user is in. For instance, I'm here in South East Asia and they're in Europe. I experience some times when I do not receive a banner ad, but in their place, they always receive all types of ads.
As long as your project is complying the the Google Admob's rules (e.g. do not display interstitial ad after the other one at a short gap of time), and you receive some ad at least once every while, then I believe you're doing fine.
I hope this helps.
I'd like to display AdMob interstitials in my app. I manage to display test ads. As far as I understand to display test ads you should add test devices, so this is what I do. When I remove the test devices though, I don't get the real ads. I'd like to test somehow that real ads will be displayed. When I remove the test devices I get interstitial(_ ad: GADInterstitial, didFailToReceiveAdWithError error: GADRequestError) delegate method called and the error is: Request Error: No ad to show. This is my code based on the instructions here:
class MoviesViewController: UIViewController {
var interstitial: GADInterstitial!
override func viewDidLoad() {
super.viewDidLoad()
interstitial = createAndLoadInterstitial()
}
func createAndLoadInterstitial() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "<Ad-Unit-ID>")
interstitial.delegate = self
let request = GADRequest()
//request.testDevices = ["<Device-Test-ID>"]
interstitial.load(request)
return interstitial
}
#IBAction func didTapStartOver(_ sender: Any) {
if interstitial.isReady {
interstitial.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
interstitial = createAndLoadInterstitial()
}
}
GADInterstitialDelegate:
extension MoviesViewController : GADInterstitialDelegate {
/// Tells the delegate an ad request succeeded.
func interstitialDidReceiveAd(_ ad: GADInterstitial) {
print("interstitialDidReceiveAd")
}
/// Tells the delegate an ad request failed.
func interstitial(_ ad: GADInterstitial, didFailToReceiveAdWithError error: GADRequestError) {
print("interstitial:didFailToReceiveAdWithError: \(error.localizedDescription)")
}
/// Tells the delegate that an interstitial will be presented.
func interstitialWillPresentScreen(_ ad: GADInterstitial) {
print("interstitialWillPresentScreen")
}
/// Tells the delegate the interstitial is to be animated off the screen.
func interstitialWillDismissScreen(_ ad: GADInterstitial) {
dismiss(animated: false, completion: nil)
print("interstitialWillDismissScreen")
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
print("interstitialDidDismissScreen")
interstitial = createAndLoadInterstitial()
}
/// Tells the delegate that a user click will open another app
/// (such as the App Store), backgrounding the current app.
func interstitialWillLeaveApplication(_ ad: GADInterstitial) {
print("interstitialWillLeaveApplication")
}
}
I added a mediation group and was able to receive one real ad. After that the issue persists (no more ads to show).
Changing the device for testing from iPad to iPhone also seems to help - the issue seems to be reproducible only on iPad.
I never used the test device feature. I always just plugged in the provided test ad id that is mentioned in their guides. When ready to test real ads, just switch to the live ad id they provide when you create the ad. Then it's good to go without changing any other code.
I have this code:
func createAndLoadInterstitial() {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-xxxxxxxxxx/xxxxx")
interstitial.delegate = self
let request = GADRequest()
interstitial.loadRequest(request)
}
override func viewDidAppear(animated: Bool) {
if (interstitial.isReady && showAd) {
showAd = false
// print("iterstitialMain is ready")
interstitial.presentFromRootViewController(self)
self.createAndLoadInterstitial()
}
else {
showAd = true
}
}
and it works. But it shows an ad every time the user taps on the back button.
I want to show an ad only one time when the user taps on the back button. Would it be better to show an ad after some time instead? For example, every 5 minutes?
Where are you setting showAd to true initially? The logic in your if statement is the main issue.
After you set showAd = false in your if statement, the next time viewDidAppear is called your else statement will be executed, setting showAd back to true.
What you should do is check your Bool, and then check interstitial.isReady. Then, in your GADInterstitial's interstitialDidDismissScreen delegate method you would update your showAd Bool and request another GADInterstitial if you'd like. You say you only want to show one GADInterstitial so requesting another is not necessary. For example:
override func viewDidAppear(animated: Bool) {
if showAd { // Should we show an ad?
if interstitial.isReady { // Is the ad ready?
interstitial.presentFromRootViewController(self)
}
}
else {
// Do nothing
}
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
// Ad was presented and dismissed
print("interstitialDidDismissScreen")
showAd = false // Don't show anymore ads
}
Also, you can change:
let request = GADRequest()
interstitial.loadRequest(request)
to just:
interstitial.loadRequest(GADRequest())
in your createAndLoadInterstitial function.
To answer the second part of your question asking if you should present an ad after some time delay, that is a violation of the AdMob program policies.
Examples of non-compliant implementations:
Interstitial ads that appear before the app has opened or after the app has closed.
Interstitial ads that are triggered after a user closes another interstitial ad.
Interstitial ads loading unexpectedly while a user is viewing the app’s content. Remember to only serve interstitials between pages of content.
Interstitial ads that trigger after every user click.
Interstitial ads that appear during periods of game play or heavy user interaction.
I am trying to load this google interstitial ad when the game is over.
if (self.interstitial.isReady)
{
self.interstitial.presentFromRootViewController(self)
}
But I am getting an error that says "Cannot convert value of type 'GameScene' to expected argument type 'UIViewController!".
I have used the same lines of code with my other apps that don't use sprite kit, is it different with sprite kit?
Yes it's different in SpriteKit because you trying to present from a SKScene and not a UIViewController.
Try this and see if it works
if (self.interstitial.isReady) {
self.interstitial.presentFromRootViewController(self.view?.window?.rootViewController)
}
If you are getting a nil crash now than you did not init the ad property correctly. You should also have some checks to ensure this does not happen.
This is how the adMob code from my gitHub helper looks.
You should have a property like so
var interstitial: GADInterstitial?
Than in view didLoad you should preload the ad
interstitial = adMobLoadInterAd()
This is pre-loading code.
func adMobLoadInterAd() -> GADInterstitial {
Debug.print("AdMob inter loading...")
let googleInterAd = GADInterstitial(adUnitID: "Your adMob ID")
googleInterAd.delegate = self
let request = GADRequest()
request.testDevices = [kGADSimulatorID] // DEBUG only
googleInterAd.loadRequest(request)
return googleInterAd
}
Than when you want to show an ad you call this
func adMobShowInterAd() {
guard interstitial != nil && interstitial!.isReady else { // calls interDidReceiveAd
Debug.print("AdMob inter is not ready, reloading")
interstitial = adMobLoadInterAd()
return
}
Debug.print("AdMob inter showing...")
interstitial?.presentFromRootViewController(self.view?.window?.rootViewController)
}
Than finally in the delegate methods you should pre load a new ad when the current ad is dismissed.
func interstitialDidDismissScreen(ad: GADInterstitial!) {
Debug.print("AdMob inter closed")
interstitial = adMobLoadInterAd()
}
I have a banner ad and an interstitial ad. They are appearing when I use the adUnitID's for testing purposes that AdMob gives you, but neither of them are showing when I use live ads. The banner just doesn't appear at all. When the interstitial ad appears, it is just completely black. The adUnitID's are correct. The ads on my other apps are currently appearing just fine. The problem occurs both when I use the iOS simulator and my device. Any ideas?
var interstitial: GADInterstitial!
func createAndLoadAd() -> GADInterstitial{
let ad = GADInterstitial(adUnitID: "ca-app-pub-7863284438864645/1835730011")
let request = GADRequest()
ad.loadRequest(request)
return ad
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
authenticateLocalPlayer()
self.bannerView.adUnitID = "ca-app-pub-7863284438864645/9358996816"
self.bannerView.rootViewController = self
let request: GADRequest = GADRequest()
self.bannerView.loadRequest(request)
self.interstitial = self.createAndLoadAd()
}
override func viewDidAppear(animated: Bool) {
_ = GADRequest()
//request.testDevices = ["2077ef9a63d2b398840261c8221a0c9b"]
showAd()
}
func showAd(){
if(self.interstitial.isReady){
print("ad ready")
self.interstitial.presentFromRootViewController(self)
}
else{
print("ad not ready")
self.interstitial = createAndLoadAd()
}
}
This is an aside, because my problem looked similar, but was not.
App ID is NOT the same as Ad Unit ID.
And, stupidly, they BOTH start with ca-app-pub- and a lot of numbers. I was using the App ID which I can guarantee 100% does NOT work.
Yes, I feel pretty silly, but the folks at Google should have made them dissimilar.
replace adUnitID with your own ad unit id in your Admob account.
make sure you setup payment method, otherwise the ads wont show up
They have both IDs that contains "~" telda and "/" slash