admob interstitial ad is never ready [duplicate] - ios

This question already exists:
admob interstitial alway returns false
Closed 6 years ago.
i have this game and i created 3 funcions in my gameviewcontroller and here they are
func getInterstitialAd(){
interstitial = GADInterstitial(adUnitID: "ca-app-pub-1782852253088296/5018877964")
let requestInterstitial = GADRequest()
interstitial.load(requestInterstitial)
}
func showAd() {
if (interstitial.isReady == true){
interstitial.present(fromRootViewController: GameViewController())
}else{
print("ad wasn't ready")
interstitial = createAd()
}
}
func createAd() -> GADInterstitial{
let interstital = GADInterstitial(adUnitID: "ca-app-pub-1782852253088296/5018877964")
interstitial.load(GADRequest())
return interstital
}
and in one of my scene called StartMenu , i call those function
var viewController: GameViewController!
and then i call the functions
viewController.getInterstitialAd()
viewController.showAd()
but it always returns ad not ready , and false for interstitial.isReady,
but also the getInterstitial function is always called .
can someone help with that please

Create a new swift file AdMobDelegate :-
import UIKit
import GoogleMobileAds
class AdMobDelegate: NSObject, GADInterstitialDelegate {
var interstitialView: GADInterstitial!
func createAd() -> GADInterstitial {
interstitialView = GADInterstitial(adUnitID: "Your Key")
interstitialView.delegate = self
let request = GADRequest()
interstitialView.loadRequest(request)
return interstitialView
}
func showAd() {
if interstitialView != nil {
if (interstitialView.isReady == true){
interstitialView.present(fromRootViewController:currentVc)
} else {
print("ad wasn't ready")
interstitialView = createAd()
}
} else {
print("ad wasn't ready")
interstitialView = createAd()
}
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("Ad Received")
if ad.isReady {
interstitialView.present(fromRootViewController: currentVc)
}
}
func interstitialDidDismissScreen(ad: GADInterstitial!) {
print("Did Dismiss Screen")
}
func interstitialWillDismissScreen(ad: GADInterstitial!) {
print("Will Dismiss Screen")
}
func interstitialWillPresentScreen(ad: GADInterstitial!) {
print("Will present screen")
}
func interstitialWillLeaveApplication(ad: GADInterstitial!) {
print("Will leave application")
}
func interstitialDidFailToPresentScreen(ad: GADInterstitial!) {
print("Failed to present screen")
}
func interstitial(ad: GADInterstitial!, didFailToReceiveAdWithError error: GADRequestError!) {
print("\(ad) did fail to receive ad with error \(error)")
}
}
Now you can use the object of this delegate class in other files as follows :-
//Define admobdelegate as global variable
var admobDelegate = AdMobDelegate()
//Declare a global variable currentVc to hold reference to current view controller
var currentVc: UIViewController!
class abc1: UIViewController {
override func viewdidload() {
super.viewdidload()
currentVc = self
admobDelegate.showAd()
}
override func viewDidAppear() {
super.viewDidAppear()
currentVc = self
}
}
class abc2: UIViewController {
override func viewdidload() {
super.viewdidload()
currentVc = self
admobDelegate.showAd()
}
override func viewDidAppear() {
super.viewDidAppear()
currentVc = self
}
}
Code is in Swift 2.2. Write your equivalent code in swift 3 in case of syntax error.

Related

Showing interstitial ad on every x loads of viewdidload

I am trying to figure out, to show an interstitial ad on every x loads of viewdidload calls.
I am loading that ad, when my viewdidload calls. But I want to load it, when the viewdidload called x time.
Any help will be appreciated. Here is my code;
class DetailController: UIViewController, GADInterstitialDelegate {
//Admob
...
...
var fullScreenAds : GADInterstitial!
//Interstitial-Ad
func createAndLoadInterstitial() -> GADInterstitial? {
fullScreenAds = GADInterstitial(adUnitID: myInterstitialID)
guard let fullScreenAds = fullScreenAds else {
return nil
}
let request = GADRequest()
request.testDevices = [ kGADSimulatorID ]
fullScreenAds.load(request)
fullScreenAds.delegate = self
return fullScreenAds
}
func interstitialDidReceiveAd(_ ad: GADInterstitial) {
print("Ads loaded.")
ad.present(fromRootViewController: self)
}
func interstitialDidFail(toPresentScreen ad: GADInterstitial) {
print("Ads not loaded.")
}
//MARK: View functions
override func viewDidLoad() {
super.viewDidLoad()
......
SVProgressHUD.show()
imageView.af_setImage(withURL: URL(string: pic.largeImageURL!)!, placeholderImage: imgPlaceHolder, filter: nil, progress: nil, progressQueue: DispatchQueue.main, imageTransition: .crossDissolve(0.2), runImageTransitionIfCached: true) { (data) in
SVProgressHUD.dismiss()
}
scrollView.delegate = self
setupScrollView()
setupGestureRecognizers()
setupBanner()
self.fullScreenAds = createAndLoadInterstitial()
}
}
You could use UserDefaults to store a count each time the view is loaded. Once it reaches it's limit, reset the count and show the ad.
Example code:
class ViewController: UIViewController {
private let adFrequency = 5
private let userDefaults: UserDefaults = .standard
private let defaultsKey = "passwordScreenViewCount"
override func viewDidLoad() {
super.viewDidLoad()
let count = userDefaults.integer(forKey: defaultsKey)
if count + 1 >= adFrequency {
userDefaults.set(0, forKey: defaultsKey)
// show the ad
} else {
userDefaults.set(count + 1, forKey: defaultsKey)
}
}
}
Take 1 global variable viewDidLoadCount and set to 0.
Suppose you want to show ad every 5 viewDidLoad(). So,
Increment viewDidLoadCount by 1 in every viewDidLoad() method and check
//take global variable
var viewDidLoadCount : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
viewDidLoadCount+=1
if viewDidLoadCount == 5 {
//send post notification to your main viewcontroller in which you have done code of ad delegate.
}
}

How can I make the singleton of AdMob Interstitial in Swift?

I'm using AdMob interstitial on my app and try to make the implementation easier.
I just found the singleton files of it in Objective-C, I can't remake them in Swift though.
How can I rewrite them in Swift?
And if I shouldn't use singleton for this implementation with some causes, please let me know.
AdMob.h
#import <Foundation/Foundation.h>
#import "AdsID.h"
#import GoogleMobileAds;
#interface AdMob : NSObject<GADBannerViewDelegate,GADInterstitialDelegate>
#property(nonatomic) GADBannerView *GADRecView; #property(nonatomic, strong) GADInterstitial *interstitial;
+ (AdMob *)sharedIncetance;
-(void)loadAdMobBanner:(UIViewController*)vc view:(UIView*)view x:(int)x y:(int)y;
-(void)loadAdMobInste:(UIViewController*)vc rate:(float)rate;
#end
AdMob.m
#import "AdMob.h"
#implementation AdMob
static AdMob *sharedData_ = nil;
+ (AdMob *)sharedInstance{
#synchronized(self){
if (!sharedData_) {
sharedData_ = [[AdMob alloc]init];
}
}
return sharedData_;
}
- (id)init {
self = [super init];
if (self) {
self.interstitial = [self createAndLoadInterstitial];
}
return self;
}
- (GADInterstitial *)createAndLoadInterstitial {
GADInterstitial *interstitial =
[[GADInterstitial alloc] initWithAdUnitID:#"XXXXXX"];
interstitial.delegate = self;
[interstitial loadRequest:[GADRequest request]];
return interstitial;
}
-(void)loadAdMobInste:(UIViewController*)vc{
if ([self.interstitial isReady]) {
[self.interstitial presentFromRootViewController:vc];
}
}
- (void)adViewDidReceiveAd:(GADBannerView *)bannerView {
NSLog(#"Banner adapter class name: %#", bannerView.adNetworkClassName);
}
#end
ViewController
[[AdMob sharedIncetance] loadAdMobInste:[self btk_parentViewController]];
UPDATE
I could implement it in Swift, but the error "whose view is not in the window hierarchy!" caused when I did the following them and ad didn't show:
Load interstitial in ViewController
Show interstitial in ViewController
Load interstitial in SecondViewController
Show interstitial in SecondViewController (ad didn't show and the error appeared)
If I used the code in Objective-C, ad showed and the error didn't appear.
AdMob
import Foundation
import GoogleMobileAds
class AdMob : NSObject, GADBannerViewDelegate, GADInterstitialDelegate{
static var sharedData_: AdMob? = nil
var interstitial: GADInterstitial?
class func sharedInstance() -> AdMob? {
let lockQueue = DispatchQueue(label: "self")
lockQueue.sync {
if sharedData_ == nil {
sharedData_ = AdMob()
}
}
return sharedData_
}
override init() {
super.init()
interstitial = createAndLoadInterstitial()
}
func createAndLoadInterstitial() -> GADInterstitial? {
let interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
func loadInste(_ vc: UIViewController?) {
if interstitial?.isReady == true {
self.interstitial?.present(fromRootViewController: vc!)
}else{
print("Ad was not realy")
}
}
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
interstitial = createAndLoadInterstitial()
}
func interstitialDidReceiveAd(_ ad: GADInterstitial) {
print("interstitialDidReceiveAd")
}
func interstitial(_ ad: GADInterstitial, didFailToReceiveAdWithError error: GADRequestError) {
print("interstitial:didFailToReceiveAdWithError: \(error.localizedDescription)")
}
func interstitialWillPresentScreen(_ ad: GADInterstitial) {
print("interstitialWillPresentScreen")
}
func interstitialWillDismissScreen(_ ad: GADInterstitial) {
print("interstitialWillDismissScreen")
}
func interstitialWillLeaveApplication(_ ad: GADInterstitial) {
print("interstitialWillLeaveApplication")
}
}
AppDelegate
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var navigationController: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
if let window = window {
let mainVC = ViewController()
navigationController = UINavigationController.init()
navigationController = UINavigationController(rootViewController: mainVC)
navigationController?.navigationBar.isHidden = true
window.rootViewController = navigationController
window.makeKeyAndVisible()
}
return true
}
}
ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
AdMob.sharedInstance()?.loadInste(self)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let secondVC = SecondViewController()
self.navigationController?.pushViewController(secondVC, animated: true)
if AdMob.sharedInstance()?.interstitial?.isReady == true {
AdMob.sharedInstance()?.interstitial?.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
}
}
SecondViewController
import GoogleMobileAds
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
AdMob.sharedInstance()?.loadInste(self)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.navigationController?.popViewController(animated: true)
if AdMob.sharedInstance()?.interstitial?.isReady == true {
AdMob.sharedInstance()?.interstitial?.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
}
}
Here the issue is that you present the AD after push the view controller so self view removed from window hierarchy that's why you getting this error "whose view is not in the window hierarchy!"
Note : Push, Present or Pop ViewController after present the AD
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// Present ad First and then Push view controller
if AdMob.sharedInstance()?.interstitial?.isReady == true {
AdMob.sharedInstance()?.interstitial?.present(fromRootViewController: self)
} else {
print("Ad wasn't ready")
}
let secondVC = SecondViewController()
self.navigationController?.pushViewController(secondVC, animated: true)
}

How to create a function which will add reward on watching an ad video

I have a counter in my game that adds a score by 1, and I want a rewarded video on my game over screen that can boost the player score by 100 but I'm not sure how to execute the function when the ad ends. Here is my code:
// FirstViewController.swift
import UIKit
import Firebase
import AVFoundation
import StoreKit
import GameKit
import Appodeal
class Page1: UIViewController, AVAudioPlayerDelegate, GADInterstitialDelegate, UIAlertViewDelegate, GKGameCenterControllerDelegate, AppodealInterstitialDelegate {
let ncObserver = NotificationCenter.default
let PlayAgainObserver = NotificationCenter.default
let AddScoreObserver = NotificationCenter.default
var player = AVAudioPlayer()
/* Variables */
var gcEnabled = Bool() // Check if the user has Game Center enabled
var gcDefaultLeaderBoard = String() // Check the default leaderboardID
var score = 0
let LEADERBOARD_ID = "ScoreID"
var interstitial: GADInterstitial!
var counter: Int = 0
var counter2: Int = 0
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var placementField: UITextField!
// #IBOutlet weak var testpulse: UIButton!
let notification = NotificationCenter.default
let notification2 = NotificationCenter.default
override func viewDidLoad() {
super.viewDidLoad()
authenticateLocalPlayer()
Appodeal.setInterstitialDelegate(self)
ncObserver.addObserver(self, selector: #selector(self.StopSoundsfunc), name: Notification.Name("StopSounds"), object:nil)
PlayAgainObserver.addObserver(self, selector: #selector(self.PlayAgainfunc), name: Notification.Name("PlayAgain"), object:nil)
AddScoreObserver.addObserver(self, selector: #selector(self.AddScorefunc), name: Notification.Name("AddScore"), object:nil)
interstitial = GADInterstitial(adUnitID: "ca-app-pub-6626761084276338/5899386416")
let request = GADRequest()
interstitial.load(request)
}
#IBAction func playAgain(_ sender: Any) {
if counter % 15 == 0 {
if interstitial.isReady {
interstitial.present(fromRootViewController: self)
interstitial = CreateAd()
} else {
print("Ad wasn't ready")
}
}
counter += 1
}
#objc func PlayAgainfunc(_ sender: Any) {
if counter % 15 == 0 {
if interstitial.isReady {
interstitial.present(fromRootViewController: self)
interstitial = CreateAd()
} else {
print("Ad wasn't ready")
}
}
counter += 1
}
#IBAction func ShowAds(_ sender: Any) {
// notification.post(name: Notification.Name("PlayAgain"), object: nil)
Appodeal.showAd(AppodealShowStyle.interstitial, rootViewController: self)
}
#IBAction func AddScore(_ sender: Any) {
notification.post(name: Notification.Name("AddScore"), object: nil)
}
// MARK: - OPEN GAME CENTER LEADERBOARD
#IBAction func checkGCLeaderboard(_ sender: AnyObject) {
let gcVC = GKGameCenterViewController()
gcVC.gameCenterDelegate = self
gcVC.viewState = .leaderboards
gcVC.leaderboardIdentifier = LEADERBOARD_ID
present(gcVC, animated: true, completion: nil)
}
// MARK: - ADD 10 POINTS TO THE SCORE AND SUBMIT THE UPDATED SCORE TO GAME CENTER
#objc func AddScorefunc(_ sender: AnyObject) {
// Add 1 point to current score
score += 1
// Submit score to GC leaderboard
let bestScoreInt = GKScore(leaderboardIdentifier: LEADERBOARD_ID)
bestScoreInt.value = Int64(score)
GKScore.report([bestScoreInt]) { (error) in
if error != nil {
print(error!.localizedDescription)
} else {
print("Best Score submitted to your Leaderboard!")
}
}
}
// MARK: - AUTHENTICATE LOCAL PLAYER
func authenticateLocalPlayer() {
let localPlayer: GKLocalPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(ViewController, error) -> Void in
if((ViewController) != nil) {
// 1. Show login if player is not logged in
self.present(ViewController!, animated: true, completion: nil)
} else if (localPlayer.isAuthenticated) {
// 2. Player is already authenticated & logged in, load game center
self.gcEnabled = true
// Get the default leaderboard ID
localPlayer.loadDefaultLeaderboardIdentifier(completionHandler: { (leaderboardIdentifer, error) in
if error != nil { print(error)
} else { self.gcDefaultLeaderBoard = leaderboardIdentifer! }
})
} else {
// 3. Game center is not enabled on the users device
self.gcEnabled = false
print("Local player could not be authenticated!")
print(error!)
}
}
}
func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) {
gameCenterViewController.dismiss(animated: true, completion: nil)
}
}
func CreateAd() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: "ca-app-pub-6626761084276338/5899386416")
interstitial.load(GADRequest())
return interstitial
}
func interstitialDidFailToLoadAd(){
NSLog("Interstitial failed to load")
}
func interstitialDidReceiveAd(_ interstitial: GADInterstitial) {
print("Interstitial adapter class name: \(String(describing: interstitial.adNetworkClassName))")
}
#IBAction func RewardedVideo(_ sender: Any) {
Appodeal.showAd(AppodealShowStyle.rewardedVideo, rootViewController: self)
}
In my "AddScorefunc" I have a counter that increases the score by 1. I want to create a similar function that increases the score by 100 but only if the rewarded video requirements are met.
If we look into the SDK integration guide of AppoDeal, they have provided delegates for all kind of ads you show through their sdk. For your case of showing a rewarded video, the delegate is AppodealRewardedVideoDelegate and here is how you can use it to get the callback and add score.
extension Page1: AppodealRewardedVideoDelegate {
func rewardedVideoDidLoadAd(){
NSLog("video ad was loaded")
}
func rewardedVideoDidFailToLoadAd(){
NSLog("video ad failed to load")
}
func rewardedVideoDidPresent(){
NSLog("video ad was presented");
}
func rewardedVideoWillDismiss(){
NSLog("video ad was closed");
}
func rewardedVideoDidFinish(_ rewardAmount: UInt, name rewardName: String!){
NSLog("video ad was fully watched");
// Add score here i.e, score += 100
}
}
In viewDidLoad of Page1, set the delegate method like this,
override func viewDidLoad() {
super.viewDidLoad()
// set delegate
Appodeal.setRewardedVideoDelegate(self)
}

GADInterstitial duplicates in view hierarchy

I have an implementation of GADInterstitial
class AdsManager {
let adsAppId = MY_ID
let fullScreenAdUnitId = MY_ID
static let manager: AdsManager = AdsManager()
private var interstitial: GADInterstitial!
private init () {
createAndLoadInterstitial()
}
func presentInterstitial(fromViewController viewController: UIViewController) {
if interstitial.isReady {
interstitial.present(fromRootViewController: viewController)
}
else {
print("Interstitial is not ready")
}
createAndLoadInterstitial()
}
private func createAndLoadInterstitial() {
//TODO: replace test ad unit id with production
interstitial = GADInterstitial(adUnitID: MY_ID)
interstitial.load(GADRequest())
}
}
and I show this ads like this:
func touchedButton(_ sender: UIButton) {
AdsManager.manager.presentInterstitial(fromViewController: self)
}
Everythink works and looks fine but when I was debugging I found something strange:
Four instances of the same view. Anyone know is it good? Or maybe I made a mistake in my AdsManager? Maybe Firebase implementation mistake?
The number of GADUIKitWebView's is dependent on the type of advertisement that is presented. A video, image, and text ad will all have different layouts. Based on the amount of memory being used I would assume it is correct.
View hierarchy of an interactive GADInterstitial advertisement:
Besides that, you do have a problem with your implementation. Your problem is in this function:
func presentInterstitial(fromViewController viewController: UIViewController) {
if interstitial.isReady {
interstitial.present(fromRootViewController: viewController)
}
else {
print("Interstitial is not ready")
}
createAndLoadInterstitial() // PROBLEM
}
You should move createAndLoadInterstitial() into the else so you only load another GADInterstitial when you actually need one. For example:
func presentInterstitial(fromViewController viewController: UIViewController) {
if interstitial.isReady {
interstitial.present(fromRootViewController: viewController)
}
else {
print("Interstitial is not ready")
createAndLoadInterstitial()
}
}
In addition to this you should implement the GADInterstitial delegate methods and load another GADInterstitial only after it has dismissed the screen. For example:
/// Called just after dismissing an interstitial and it has animated off the screen.
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
print("interstitialDidDismissScreen")
createAndLoadInterstitial()
}

interstitialWillDismissScreen only being called once

I am using Admob interstitials in my swift project and I am having trouble reloading the ads. The first interstitial displays fine, and when interstitialWillDismissScreen is called, it exits back to the game and reloads a new interstitial as it's supposed to. However, neither interstitialDidReceiveAd nor interstitialWillDismissScreen are called again, so after the second ad is displayed, no other ads come through. What am I missing?
import GoogleMobileAds
let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
class GameScene: SKScene, GKGameCenterControllerDelegate, GADInterstitialDelegate {
var interstitial: GADInterstitial!
override func didMoveToView(view: SKView) {
//preload interstitial ad
if NSUserDefaults.standardUserDefaults().boolForKey("paidToRemoveAds") == false {
interstitial = loadAd()
}
interstitial.delegate = self
}
func gameOver() {
runGoogleAd()
}
func loadAd() -> GADInterstitial {
let ad = GADInterstitial(adUnitID: "ca-app-pub-2963481692578498/7292484569")
let request = GADRequest()
request.testDevices = [kGADSimulatorID]
ad.loadRequest(request)
return ad
}
func runGoogleAd() {
if interstitial.isReady {
interstitial.presentFromRootViewController((appDelegate.window?.rootViewController)!)
}
}
func interstitialDidReceiveAd(ad: GADInterstitial!) {
print("ad loaded")
}
func interstitialWillDismissScreen(ad: GADInterstitial!) {
interstitial = loadAd()
print("loading new ad")
}
}
I assume loadAd() creates a new instance? You need to set the delegate on the new instance:
func interstitialWillDismissScreen(ad: GADInterstitial!) {
interstitial = loadAd()
interstitial.delegate = self // <-- You forgot this.
print("loading new ad")
}
Actually you should probably set the delegate in loadAd() since it is an instance member of this class.

Resources