I'm developing an iOS application using Swift2 and Xcode7. I'm trying to implement AdMob but it doesn't display my interstitial ad.
override func viewDidLoad() {
super.viewDidLoad()
_interstitial = createAndLoadInterstitial()
}
func createAndLoadInterstitial()->GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "interstitial_ID")
let gadRequest:GADRequest = GADRequest()
gadRequest.testDevices = ["test device id"]
interstitial.delegate = self
interstitial?.loadRequest(gadRequest)
return interstitial!
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
_interstitial?.presentFromRootViewController(self)
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print(error.localizedDescription)
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
_interstitial = createAndLoadInterstitial()
}
I receive this error:
Request Error: No ad to show.
Request Error: No ad to show.
means that your request was successful but that Admob has no ad to show for your device at this time. The best way to ensure that you always have ads to show is to use mediation so that an unfulfilled request falls through to another ad network. Admob provides good mechanisms to do that.
You should have two Ad Unit ID's. One for your GADBannerView and one for your GADInterstitial. Make sure your Ad Unit ID supplied by AdMob for your interstitial is exactly the same as what they've given you. Update to the latest AdMob SDK, currently 7.5.0. Also consider calling presentFromRootViewController(self) at specific intervals or once the user completes a desired action. The way you have it setup now will keep presenting interstitials one after another because you are sending requests for new interstitials every time one is dismissed and then displaying the interstitial as soon as it receives an ad.
import UIKit
import GoogleMobileAds
class ViewController: UIViewController, GADInterstitialDelegate {
var myInterstitial : GADInterstitial?
override func viewDidLoad() {
super.viewDidLoad()
myInterstitial = createAndLoadInterstitial()
}
func createAndLoadInterstitial()->GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "Your Ad Unit ID")
interstitial.delegate = self
interstitial?.loadRequest(GADRequest())
return interstitial
}
#IBAction func someButton(sender: AnyObject) {
myInterstitial?.presentFromRootViewController(self)
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("interstitialDidReceiveAd")
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print(error.localizedDescription)
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
print("interstitialDidDismissScreen")
myInterstitial = createAndLoadInterstitial()
}
Related
I try to setup interstitial ads in my app. If I use a test unit ID, ad shows fine, but if I try to use the real unit ID, I see the error "Ad wasn't ready". What I do wrong? Thank for any help!
My code:
import UIKit
import GoogleMobileAds
class ViewController: UIViewController {
var interstitial: GADInterstitial!
override func viewDidLoad() {
super.viewDidLoad()
interstitial = createAndLoadInterstitial()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
if self.interstitial.isReady {
self.interstitial.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
}
}
func createAndLoadInterstitial() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "AdMob Real Unit ID")
interstitial.delegate = self
let request = GADRequest()
GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = ["my device ID from console"]
interstitial.load(request)
return interstitial
}
}
extension ViewController: GADInterstitialDelegate {
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitial = createAndLoadInterstitial()
}
}
Console:
Launching interstitial ad immediately after page load is disallowed.
Refer Disallowed Interstitial implementation policy https://support.google.com/admob/answer/6201362?hl=en
A common issue is that even though you may intend for the ad to load
in between page content, the ad itself appears shortly after a new
page of content has loaded due to carrier latency. To prevent this
from happening, we recommend you pre-load the interstitial in advance.
To learn more about how to pre-load your interstitial ad, please
follow the AdMob Interstitial Ad developer guidelines for apps
developed for Android and iOS.
Only load the ad on viewDidLoad () https://developers.google.com/admob/ios/interstitial
class ViewController: UIViewController {
var interstitial: GADInterstitial!
override func viewDidLoad() {
super.viewDidLoad()
interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
let request = GADRequest()
interstitial.load(request)
}
}
and then Interstitials should be displayed during natural pauses in the flow of an app. Between levels of a game is a good example, or after the user completes a task.
#IBAction func doSomething(_ sender: AnyObject) {
...
if interstitial.isReady {
interstitial.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
}
Solved:
To display your ad units, your AdMob account must be verified.
You must see message in the Google AdMob Console:
Your account is approved
Congratulations! We've verified your account information and your ad serving is enabled.
So, I had the interstitial ads working fine by following the code on the Admob website and then recently I updated my pods and with it the GoogleAdMob SDK.
Now when my interstitial Ad should present, nothing happens and in the console I have this error:
<GoogleThe provided view controller is not being presented.
[ProcessSuspension] 0x110adfbd0 - ProcessAssertion::processAssertionWasInvalidated()
Here is my code:
extension FirstViewController: GADInterstitialDelegate {
func showInterstitialAd() {
if interstitial.isReady {
interstitial.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
}
func createAndLoadInterstitial() -> GADInterstitial {
var interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitial = createAndLoadInterstitial()
}
}
In viewDidLoad I call:
func setUpInterstitial() {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
interstitial.delegate = self
let request = GADRequest()
interstitial.load(request)
}
and in ViewWillAppear
if InterstitialAd.counter >= 3 { self.showInterstitialAd(); InterstitialAd.counter = 0}
The intended logic is every 3 times a user views a page, namely FirstViewController, an interstitial ad shows.
Thank you in advance :)
You can update your code like below:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if InterstitialAd.counter >= 3 {
self.showInterstitialAd();
InterstitialAd.counter = 0
}
}
Remove your code from viewWillAppear.
I implemented a test adMob with Firebase:
override func viewDidLoad() {
super.viewDidLoad()
interstitial = createAndLoadInterstitial()
interstitial.delegate = self
....}
func createAndLoadInterstitial() -> GADInterstitial {
var interstitial = GADInterstitial(adUnitID: "testVideo")
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func interstitialWillDismissScreen(_ ad: GADInterstitial) {
print("interstitialWillDismissScreen")
UserDefaults.standard.set(false, forKey: "adWasShowing")
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
if ... {
...
}
interstitial = createAndLoadInterstitial()
print("interstitialDidDismissScreen")
}
The problem is when I get an ad (5sec video) and take the app to background and then to foreground again
interstitialWillDismissScreen and interstitialDidDismissScreen
automatically gets called resulting in closing the ad. I think many users will use this exploit to not stay on the video. Any idea on how to solve this?
I tried to set up a bool in UserDefaults in the "interstitialWillPresentScreen" and check it at "applicationWillEnterForeground", but I don't like this idea and also the interstitial request is not yet loaded (interstitialRequest must be recreated for every ad).
When my callButton is clicked it rings a phone number, I want to display my interstitial ad before the call is made. I have tested my ad on the "IBAction function ad" button and it works on the button but when I call it on the callButton func it will not work and goes straight to making a call.
class ProfilePageViewController: UIViewController, MFMessageComposeViewControllerDelegate, UITableViewDelegate, UIAlertViewDelegate, GADInterstitialDelegate {
#IBAction func ad(_ sender: Any) {
if self.interstitialAd.isReady {
self.interstitialAd.present(fromRootViewController: self)
}
}
#IBAction func callButton(_ sender: Any) {
if let contactopt = contact{
if let url = NSURL(string: "tel://\(contactopt)") {
// UIApplication.shared.openURL(url as URL)
UIApplication.shared.open(url as URL, options: [:], completionHandler: nil)
}
}
}
var interstitialAd: GADInterstitial!
func reloadInterstitialAd() -> GADInterstitial {
var interstitial = GADInterstitial(adUnitID: "ca-app-pub-/6966780536")
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
self.interstitialAd = reloadInterstitialAd()
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitialAd = reloadInterstitialAd()
}
override func viewDidLoad() {
self.interstitialAd = GADInterstitial(adUnitID: "ca-app-pub-/6966780536")
let request = GADRequest()
request.testDevices = ["2077ef9a63d2b398840261c8221a0c9b"]
self.interstitialAd.load(request)
self.interstitialAd = reloadInterstitialAd()
super.viewDidLoad()
}
}
Of course it goes to making a call. That's what you're telling it to do with UIApplication.shared.open.
Make the call once the ad has been dismissed in interstitialDidDismissScreen.
Also check to see if there is an ad to present, interstitialAd.isReady. If there is no ad to present go straight to making the call.
You're also doing the same thing twice in your viewDidLoad:
// Sets up an ad
self.interstitialAd = GADInterstitial(adUnitID: "ca-app-pub-/6966780536")
let request = GADRequest()
request.testDevices = ["2077ef9a63d2b398840261c8221a0c9b"]
self.interstitialAd.load(request)
// Creates a new ad
self.interstitialAd = reloadInterstitialAd()
Just call self.interstitialAd = reloadInterstitialAd().
I believe your problem has to do with the synchrony of the present method on the interstitial. I do not know what the implementation is, but it seems like the ad's presentation does not block the thread on which it was called. You should try implementing GADInterstitialDelegate to grab the event when the ad is presented then proceed to make your call from there.
Try this:
GADInterstitial is a one time use object. That means once an
interstitial is shown, hasBeenUsed returns true and the interstitial
can't be used to load another ad. To request another interstitial,
you'll need to create a new GADInterstitial object. The best practice,
as shown above, is to have a helper method to handle creating and
loading an interstitial.
func createAndLoadInterstitial() -> GADInterstitial {
var interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitial = createAndLoadInterstitial()
}
#IBAction func ad(_ sender: Any) {
if self.interstitialAd.isReady {
self.interstitialAd.present(fromRootViewController: self)
}
}
Right now it only shows the full page ad one time. When I go back and press the button again it does not show. I would like it to show overtime my button is clicked. I have my AdMob hooked up to my Firebase project.
class FirstViewController: UIViewController, UIAlertViewDelegate {
var interstitial: GADInterstitial!
#IBAction func loadAd(_ sender: Any) {
if (interstitial.isReady){
interstitial.present(fromRootViewController: self)
}
}
override func viewDidLoad() {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-11111111/9758796532")
let request = GADRequest()
interstitial.load(request)
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You need to create GAD request every time.
GADInterstitial is a one time use object. That means once an
interstitial is shown, hasBeenUsed returns true and the interstitial
can't be used to load another ad. To request another interstitial,
you'll need to create a new GADInterstitial object. The best practice,
as shown above, is to have a helper method to handle creating and
loading an interstitial.
#IBAction func loadAd(_ sender: Any) {
interstitial = GADInterstitial(adUnitID: "ca-app-pub-11111111/9758796532")
interstitial.delegate = self
let request = GADRequest()
interstitial.load(request)
}
And while loaded successfully you need to present at delegate method
optional func interstitialDidReceiveAd(_ ad: GADInterstitial!){
if (interstitial.isReady){
interstitial.present(fromRootViewController: self)
}
}
optional func interstitialWillDismissScreen(_ ad: GADInterstitial!){
interstitial.delegate = nil
interstitial = nil
}
optional func interstitialDidFail(toPresentScreen ad: GADInterstitial!){
interstitial.delegate = nil
interstitial = nil
}
More : https://firebase.google.com/docs/admob/ios/interstitial
When dismissing the interstitial we have to create and make load request for next interstitial ads.
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitial = createAndLoadInterstitial()
}
The best place to allocate another interstitial is in the interstitialDidDismissScreen: method on GADInterstitialDelegate so that the next interstitial starts loading as soon as the previous one is dismissed. You may even consider breaking out interstitial initialization into its own helper method:
Source: https://firebase.google.com/docs/admob/ios/interstitial