Placing iAd and Admob banner is causing an issue - ios

I've been trying to do the following with iAd and Admob banner:
First i placed iAd over Admob banner in storyboard and I've added all the needed constraints, if iAd fail to receive i will show Admob banner if i received iAd i am gonna hide Admob and then show iAd banner..etc.
The issue doesn't happen all the time, while admob banner is showing iAd comes and push the admob banner to the top without hiding it. but in the code it should hide it.this issue happens after hiding and showing, hiding and showing many times..
Please check the following screenshot.
ViewController code:
#IBOutlet weak var Gbanner: GADBannerView!
#IBOutlet weak var AbannerView: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
AbannerView.delegate = self
self.canDisplayBannerAds = true
showadmob()
// Do any additional setup after loading the view, typically from a nib.
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("didFailToReceiveAdWithError")
AbannerView.hidden = true
Gbanner.hidden = false
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
println("bannerViewActionDidFinish")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
println("bannerViewDidLoadAd")
Gbanner.hidden = true
AbannerView.hidden = false
}
func bannerViewWillLoadAd(banner: ADBannerView!) {
println("bannerViewWillLoadAd")
}
func showadmob(){
self.Gbanner.adUnitID = "somethingelsehere"
self.Gbanner.rootViewController = self
var request: GADRequest = GADRequest()
self.Gbanner.loadRequest(request)
}
Download project here : https://yadi.sk/d/1VcjfJG9ixNZg

If you're implementing your own ADBannerView then you need to remove self.canDisplayBannerAds = true from your viewDidLoad.
self.canDisplayBannerAds = true can be used for a no hassle way of implementing iAd banners in your application. This will create an ADBannerView for you and show or hide the ADBannerView depending on whether it receives an ad or not from the iAd network.
You either implement your own ADBannerView or use self.canDisplayBannerAds = true, not both.

Related

Admob banner for app with iPad Multitasking / Split View enabled (Swift)

I am making an app for iPad with multitasking enabled and right now I am trying to implement an Admob banner.
There is an article about doing that in case of multitasking enabled (https://developers.google.com/admob/ios/multiscene?hl=ru) but all code there is written in Objective-C when I'm using Swift.
I tried to translate it but I have no idea how to do that for the piece of code below. What is "requestInitialized"? What it should do and how to write it in Swift?
If anyone has a full code for successful implementing an Admob banner in multitasking app, please help me with it
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if (!_requestInitialized) {
[self loadInterstitial];
_requestInitialized = YES;
}
}
For SwiftUI you can add this :
request.scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
GoogleAdmob does offer a quick-start here that does show you Swift.. I will also provide some instructions.
Make sure you have the GoogleMobileAds pod added to your project and have the correct plist setup.
In your didFinishLaunchingWithOptions in your AppDelegate.swift add the following:
GADMobileAds.sharedInstance().start(completionHandler: nil)
Drag and drop a normal UIView into your storyboard, give it a width of 320 and a height of 50. Then you can change the class of the view to a GADBannerView. Then use the code below and make sure your IBOutlet is connected.
import UIKit
import GoogleMobileAds
class ViewController: UIViewController, GADBannerViewDelegate {
#IBOutlet weak var bannerView: GADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
bannerView.adUnitID = "ca-app-pub-3940256099942544/6300978111" // Test Banner ID, replace with your ID here.
bannerView.rootViewController = self
bannerView.load(GADRequest())
bannerView.delegate = self
}
// MARK: - GADBannerViewDelegate
func adViewDidReceiveAd(_ bannerView: GADBannerView) {
print("Received Ad")
}
func adView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: GADRequestError) {
print(error)
}
}

How to check if an AdMob banner ad has been loaded? (Swift 3)

I have my AdMob ads all setup and working, but I want to make an animation for them when they first load in. For example, I have a banner ad right below the bottom of the screen, and when it loads I want it to go up. The animation I have right now:
UIView.animate(withDuration: 1, animations: {
self.banner.frame.origin.y -= 350
})
works just fine, but only shows to the user if the ad loaded fast enough. What can I do to check?
You could achieve it by setting the delegate of the GADBannerView to the desired class, for instance the self view controller:
override func viewDidLoad() {
super.viewDidLoad()
// let's assume that you init the banner view somewhere in your code...
adMobBannerView.delegate = self
}
And then implementing adViewDidReceiveAd(_ bannerView: GADBannerView!):
Tells the delegate that an ad request successfully received an ad. The
delegate may want to add the banner view to the view hierarchy if it
hasn’t been added yet.
adding to it your animation code, as follows:
func adViewDidReceiveAd(_ bannerView: GADBannerView!) {
UIView.animate(withDuration: 1, animations: {
self.banner.frame.origin.y -= 350
})
}

How to use GADBannerViewDelegate to perform action on adViewDidReceiveAd

I have a banner view and want to have a custom close button. My problem is that the button is displayed before the ad is loaded and displayed.
class RootVC: UIViewController, GADBannerViewDelegate {
var googleAdBanner: GADBannerView!
var googleBannerCloseBtn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
googleAdBanner = GADBannerView(frame:CGRectMake(0,0,100,100))
googleAdBanner.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2)
googleAdBanner.adUnitID = "xx"
googleAdBanner.rootViewController = self
googleAdBanner.loadRequest(GADRequest())
adViewWillPresentScreen(googleAdBanner)
googleAdBanner.delegate = self
self.view.addSubview(googleAdBanner)
}
func adViewWillPresentScreen(bannerView: GADBannerView!) {
googleBannerCloseBtn = UIButton(frame: CGRectMake( 5 , 5, 25, 25))
googleBannerCloseBtn.backgroundColor = UIColor.clearColor()
googleBannerCloseBtn.setImage(UIImage(named: "closeBtn"), forState: .Normal)
googleBannerCloseBtn.setTitle("Click Me", forState: UIControlState.Normal)
googleBannerCloseBtn.addTarget(self, action: #selector(RootVC.buttonAction(_:)), forControlEvents: UIControlEvents.TouchUpInside)
googleBannerCloseBtn.tag = 1
googleAdBanner.addSubview(googleBannerCloseBtn)
}
How do I present the button only when the GADBannerView has loaded an ad and is presented?
Same behavior with adViewDidReceiveAd. The button is visible, even if the GADBannerView is "invisible" because there is no ad loaded currently.
Screens as requested. As you see, the button, that is a subView of the GADBannerView is displayed before the ad itself is displayed.
I've commented out alot of the logic in this example. The only thing that I didn't mention was that you will need to create two Ad Unit ID's. One for your GADBannerView and one for your GADInterstitial on AdMob.com.
import UIKit
import GoogleMobileAds // Import AdMob
class ViewController: UIViewController, GADBannerViewDelegate, GADInterstitialDelegate { // Include our delegates
// Create our ads
var banner = GADBannerView(adSize: kGADAdSizeBanner) // kGADAdSizeBanner is a default banner size
var interstitial = GADInterstitial(adUnitID: "YourInterstitialAdUnitID")
override func viewDidLoad() {
super.viewDidLoad()
// View has loaded so lets setup our ads initially
setupAds()
}
// MARK: - Setup Ads
func setupAds() {
// Setup our banner ad
banner.adUnitID = "YourBannerAdUnitID"
banner.rootViewController = self
banner.delegate = self
// Hide our banner initially until it loads an ad
// Not doing this is why your close button was visible
// GADBannerView's with no ad are essentially "clear", not hidden
banner.alpha = 0.0
banner.loadRequest(GADRequest())
// Position banner on bottom of view
banner.frame = CGRect(x: 0.0,
y: view.frame.height - banner.frame.height,
width: view.frame.width,
height: banner.frame.height)
// Create your button here and add it as a subview to banner
// banner.addSubview(closeButton)
view.addSubview(banner)
// Setup our interstitial ad initially
interstitial.delegate = self
interstitial.loadRequest(GADRequest())
}
// MARK: - Load Interstitial Ad
func loadFullScreenAd() {
// GADInterstitial's are single use. You have to create a new GADInterstitial for each presentation
// So, if you'd like to show more than one GADInterstitial in your apps session we need this
// This func will be used to create a new GADInterstitial after one has been displayed and dismissed
interstitial = GADInterstitial(adUnitID: "YourInterstitialAdUnitID")
interstitial.delegate = self
interstitial.loadRequest(GADRequest())
}
// MARK: - Show Interstitial Ad
func showFullScreenAd() {
// Call this function when you want to present the interstitial ad
// ie. game over, transition to another vc, etc...
// Make sure you give atleast a few seconds for this ad to load before atempting to present it
// For example, don't try to present this ad in viewDidAppear
// Check if the interstitial ad is loaded before trying to present it
if interstitial.isReady {
interstitial.presentFromRootViewController(self)
}
}
// MARK: - Close Button Action
func closeButtonAction() {
// This is where we will handle your close button that you've added to your GADBannerView
// You can handle this two ways and it depends on what you'd like to do
// If you don't want to show the banner ad again during the entire app session you would hide the banner
// This way even if we change the alpha values in our delegate methods the banner will remain hidden
banner.hidden = true
// Another way you can handle the close button would be to hide the banner until another banner ad is loaded
// I believe the refresh rate for banner ads is 45-60 seconds. You can customize the refresh time on AdMob.com
// So, this way if the user tapped the close button the banner would fade out
// But, when another banner ad is loaded the banner would fade back in because of the code in our adViewDidReceiveAd delegate method
UIView.animateWithDuration(0.2) {
self.banner.alpha = 0.0
}
/////* Choose which way you'd like to handle the close button and remove the code for the other */////
}
// MARK: - GADBannerView Delegate Methods
func adViewDidReceiveAd(bannerView: GADBannerView!) {
print("adViewDidReceiveAd")
// We received an ad so lets show it
// You could even fade in the banner if you'd like
UIView.animateWithDuration(0.2) {
self.banner.alpha = 1.0
}
}
func adView(bannerView: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
print("banner didFailToReceiveAdWithError: \(error)")
// We received an error when trying to load our GADBannerView
// Lets hide it because we don't have an ad
// You could also fade this out if you'd like
UIView.animateWithDuration(0.2) {
self.banner.alpha = 0.0
}
}
// MARK: - GADInterstitial Delegate Methods
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("interstitialDidReceiveAd")
}
func interstitialWillPresentScreen(ad: GADInterstitial!) {
print("interstitialWillPresentScreen")
// If you needed to pause anything in your app this would be the place to do it
// ie. sounds, game state, etc...
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
print("interstitialDidDismissScreen")
// The GADInterstitial has been shown and dismissed by the user
// Lets load another one for the next time we want to show a GADInterstitial
loadFullScreenAd()
// If you paused anything in the interstitialWillPresentScreen delegate method this is where you would resume it
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print("interstitial didFailToReceiveAdWithError: \(error)")
}
}
Also, if you plan on presenting the GADInterstitial often in your application I'd recommend disabling video ads on AdMob.com for that Ad Unit ID. AdMob interstitial video ads disable the close button for 5 seconds, kind of like the skip button on YouTube, and will aggravate your users instantaneously. If you're rarely showing the GADInterstitial then I'd leave the video ads enabled.

iad won't move content to fit in (it covers the content)

I'm working on an app for both iphone/ipad all sizes. I've used the storyboard to place all the elements on screen: labels, buttons and images. Everything works perfectly. I want to place an iad at the bottom of the screen. So I places an iad from the object library and constrained it to the bottom of the screen, without constraining it to the other objects on the view. I've read that the iad has already the ability to push all content (resize) for it to fit on the screen. However when I run my app on the simulator, 6 out of 10 times the iad pushes the content up to make space for it to display. The other 4 times the iad covers the bottom label and button. It happens on all the simulator devices (5, 5s, 6, 6s, 6+ 6+s, ipad 2, ipad pro, ipad air, ipad air2, ipad retina.)
I'm using the following script to display the iad:
#IBOutlet weak var adBannerView: ADBannerView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.canDisplayBannerAds = true
self.adBannerView?.delegate = self
self.adBannerView?.hidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func bannerViewWillLoadAd(banner: ADBannerView!) {
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
self.adBannerView?.hidden = false
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
self.adBannerView?.hidden = true
}
Does anyone know or have an Idea on how to fix the problem I'm having?
Also in the apple manual it says that if iad fails to load it should be pushed offscreen. Do I need to write code to do this or will it do it automatically by its self?
iad pushes content to fit in, screen shot
iad covers the content, screen shot

App approved but no AdMob ads appearing

My iOS application was denied due to Apple not finding my ads during the review process. I uploaded my application again, included directions on how to see the ads, and it was approved today. Now, once my friends and family downloaded the application no ads are showing up. I checked my AdMob account and no impressions showed up so I don't know what's wrong. Has anyone had this happened to them? Also, it hasn't been 24hrs yet since the app was approved. Since Apple approved it I assume that they have seen the ads. My application shows ads when you start using the filters after you pick a photo. AdMob shows 61 impressions, 61 requests, and 100% fill rate.
// Initialize Apple iAd banner
func initiAdBanner() {
iAdBannerView = ADBannerView(frame: CGRectMake(0, self.view.frame.size.height, 0, 0) )
iAdBannerView.delegate = self
iAdBannerView.hidden = true
view.addSubview(iAdBannerView)
}
// Initialize Google AdMob banner
func initAdMobBanner() {
if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
// iPad banner
adMobBannerView.adSize = GADAdSizeFromCGSize(CGSizeMake(728, 90))
adMobBannerView.frame = CGRectMake(0, self.view.frame.size.height, 728, 90)
} else {
// iPhone banner
adMobBannerView.adSize = GADAdSizeFromCGSize(CGSizeMake(320, 50))
adMobBannerView.frame = CGRectMake(0, self.view.frame.size.height, 320, 50)
}
adMobBannerView.adUnitID = "AdMobPublisherID"
adMobBannerView.rootViewController = self
adMobBannerView.delegate = self
// adMobBannerView.hidden = true
view.addSubview(adMobBannerView)
var request = GADRequest()
adMobBannerView.loadRequest(request)
}
// Hide the banner
func hideBanner(banner: UIView) {
if banner.hidden == false {
UIView.beginAnimations("hideBanner", context: nil)
// Hide the banner moving it below the bottom of the screen
banner.frame = CGRectMake(0, self.view.frame.size.height, banner.frame.size.width, banner.frame.size.height)
UIView.commitAnimations()
banner.hidden = true
}
}
// Show the banner
func showBanner(banner: UIView) {
if banner.hidden == true {
UIView.beginAnimations("showBanner", context: nil)
// Move the banner on the bottom of the screen
banner.frame = CGRectMake(0, (self.view.frame.size.height-70) - banner.frame.size.height,
banner.frame.size.width, banner.frame.size.height);
UIView.commitAnimations()
banner.hidden = false
}
}
// iAd banner available
func bannerViewWillLoadAd(banner: ADBannerView!) {
println("iAd loaded!")
hideBanner(adMobBannerView)
showBanner(iAdBannerView)
}
// NO iAd banner available
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("iAd can't looad ads right now, they'll be available later")
hideBanner(iAdBannerView)
var request = GADRequest()
adMobBannerView.loadRequest(request)
}
// AdMob banner available
func adViewDidReceiveAd(view: GADBannerView!) {
println("AdMob loaded!")
hideBanner(iAdBannerView)
showBanner(adMobBannerView)
}
// NO AdMob banner available
func adView(view: GADBannerView!, didFailToReceiveAdWithError error: GADRequestError!) {
println("AdMob Can't load ads right now, they'll be available later \n\(error)")
hideBanner(adMobBannerView)
}
Ads are now appearing in your application. When your application is approved by Apple it still must be approved by the iAd team to receive iAd advertisements. This can take a few additional days. As a result, neither of your advertisements were being shown in your application. You can test this by going to Settings>Developer>and setting your fill rate to 0% on your development device. The reason neither ad is being shown if iAd fails to load initially is because of this function:
// Show the banner
func showBanner(banner: UIView) {
if banner.hidden == true {
UIView.beginAnimations("showBanner", context: nil)
// Move the banner on the bottom of the screen
banner.frame = CGRectMake(0, (self.view.frame.size.height-70) - banner.frame.size.height,
banner.frame.size.width, banner.frame.size.height);
UIView.commitAnimations()
banner.hidden = false
}
}
You're checking for if banner.hidden == true but your adMobBannerView's hidden value is never set to true until an iAd banner is loaded. Seeing as no iAd banner was being loaded prior to the approval by iAd's team this condition was never being met. This condition will also never be met in countries that do not support iAd or if iAd fails to load an ad initially.
Also, there's alot of jumping around when your ads load due to you animating them on and off the screen. A more elegant approach would be to animate their alpha values so the user does not notice when your ads change. You can also eliminate alot of your code. I've rewritten what you're trying to accomplish and commented out the reasoning behind it.
import UIKit
import iAd
class ViewController: UIViewController, ADBannerViewDelegate, GADBannerViewDelegate {
var iAdBannerView : ADBannerView = ADBannerView()
var adMobBannerView : GADBannerView = GADBannerView()
override func viewDidLoad() {
super.viewDidLoad()
loadAds()
}
func loadAds() {
// iAd
// Changed banners width to match the width of the view it is on
// You need to set the y origin relative to your view. Not a static number.
iAdBannerView = ADBannerView(frame: CGRectMake(0, self.view.frame.size.height - iAdBannerView.frame.height, self.view.frame.size.width, iAdBannerView.frame.height))
iAdBannerView.delegate = self
view.addSubview(iAdBannerView)
// Hide iAd initially
iAdBannerView.alpha = 0.0
// AdMob
// Changed adSize to Googles set banner size
adMobBannerView.adSize = kGADAdSizeBanner
// Changed banners width to match the width of the view it is on
// You need to set the y origin relative to your view. Not a static number.
adMobBannerView.frame = CGRectMake(0, self.view.frame.size.height - adMobBannerView.frame.height , self.view.frame.size.width, adMobBannerView.frame.height)
adMobBannerView.rootViewController = self
adMobBannerView.delegate = self
adMobBannerView.adUnitID = "AdMobPublisherID"
// Dont need var request = GADRequest()
adMobBannerView.loadRequest(GADRequest())
// Do not hide AdMob initially
view.addSubview(adMobBannerView)
}
// Use bannerViewDidLoadAd function so we know ad is fully loaded
func bannerViewDidLoadAd(banner: ADBannerView!) {
println("iAd has an ad to show")
// Animate fade of banners
UIView.beginAnimations(nil, context: nil)
// Show iAd
iAdBannerView.alpha = 1.0
// Hide AdMob
adMobBannerView.alpha = 0.0
UIView.commitAnimations()
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
println("iAd failed to load an ad because \(error)")
// Animate fade of banners
UIView.beginAnimations(nil, context: nil)
// Hide iAd
iAdBannerView.alpha = 0.0
// Show AdMob
adMobBannerView.alpha = 1.0
UIView.commitAnimations()
}
This favors iAd and falls back to AdMob if iAd fails to load an ad. You don't need to check for when AdMob fails to load an ad as its fill rate is almost always 100%, and if there's no AdMob ad I doubt there's an iAd ad to show.
You would need to look at the device logs to determine why no ads were shown. In all likelihood, there were no ads available from the ad server at that point in time.
This is a normal state of affairs and why you should use mediation to ensure you have a back up network.

Resources