AdMob広告をXcode(Swift)でiOSアプリに表示する手順とエラー対処方法
2017/11/26
iAdが終了したらしいので、AdMob(Goole Mobile Ads ) を導入、掲載することにしました。
上記画像のようにバナー広告が無事表示されました。
その流れと途中のエラーの対処方法などについてメモしておきます。
なお、Xcodeのバージョンは8.3.2、Swift3で書いています。
Contents
- 1 Xcodeでのフレームワークのインポート
- 2 XcodeのViewController.swiftでのコーディング(バナー広告)
- 3 No such module 'GoogleMobileAds'のエラー解決方法
- 4 実機でテストしても広告が表示されない
- 5 広告ID(Advertising Identifier又はIDFA)で「はい」を選ぶ
- 6 XcodeのViewController.swiftでのコーディング(全画面広告、インタースティシャル広告)
- 7 com.apple.WebKit.WebContent drops 113 error: Could not find specified serviceとかGoogle Cannot present interstitial. It is not ready.の解決法
- 8 Request Error: Will not send request because interstitial object has been usedの解決法
Xcodeでのフレームワークのインポート
Admobの登録手順やフレームワークの導入などについては、Swift製iOSアプリの広告をiAdからAdMobへを参考にさせていただきました。
「Build Phases」の「Link Binary With Libraries」から以下の11個のフレームワークを導入するようです。
AdSupport.framework
AudioToolbox.framework
AVFoundation.framework
CoreGraphics.framework
CoreMedia.framework
CoreTelephony.framework
EventKit.framework
EventKitUI.framework
MessageUI.framework
StoreKit.framework
SystemConfiguration.framework
さらに、AdMobの公式サイトからダウンロードした「GoogleMobileAdsSdkiOS-7.22.0(この時の最新バージョンは7.22.0だった模様)」のフォルダから「GoogleMobileAds.framework」のファイルをドラッグ&ドロップするわけですが、これについてはコツがありました。後述します。
XcodeのViewController.swiftでのコーディング(バナー広告)
上記サイトを参考にさせていただき、最初に「import GoogleMobileAds」を記入。
そしてclass ViewController: {}に、上記サイトで参考にさせていただいた通りの以下のコードを書く。
// AdMob広告設定 var bannerView: GADBannerView = GADBannerView() bannerView = GADBannerView(adSize:kGADAdSizeBanner) bannerView.frame.origin = CGPoint(x:0, y:20) bannerView.frame.size = CGSize(width:self.view.frame.width, height:bannerView.frame.height) // AdMobで発行された広告ユニットIDを設定 bannerView.adUnitID = "ca-app-pub-***" bannerView.delegate = self bannerView.rootViewController = self let gadRequest:GADRequest = GADRequest() // テスト用の広告を表示する時のみ使用(申請時に削除) //gadRequest.testDevices = ["***"] bannerView.load(gadRequest) self.view.addSubview(bannerView)
ここで注意点が。
まず、class ViewController:のところでデリゲートを宣言しておかなければなりません。
これを忘れると全く動作しません。
次に、swift3では、CGPointMake(0, 20)というswift2での書き方をCGPoint(x:0, y:20)に修正します。
(縦軸の座標を20に設定しているのは、バナー広告の配置が上すぎるとiPhoneのバッテリーとか時間とかが表示されるエリアとかぶるので。)
また、CGSizeMake(self.view.frame.width, bannerView.frame.height)という書き方をCGSize(width:self.view.frame.width, height:bannerView.frame.height)に修正。
テスト用の広告を表示する際の自分の端末のIDは、実行時にXcodeのデバッグエリアに表示されるのでそれをコピペ。
No such module 'GoogleMobileAds'のエラー解決方法
で、「GoogleMobileAds.framework」のファイルのドラッグアンドドロップのコツ。
GoogleMobileAds.frameworkについても同様に「Link Binary With Libraries」にドラッグ&ドロップすると、なんとなくうまくいったような気がするのですが、そうすると「ViewController.swift」の「var bannerView: GADBannerView = GADBannerView()」のところで「No such module 'GoogleMobileAds'」というエラーが表示されてbuild failedになるんですよね。
これ全然解決方法がわからなかったのですが、まさにアプリに広告のフレームワークを追加したのに「No such module 'GoogleMobileAds'」と表示される問題の解決方法(Xcode7,Swift2.0)の手法で解決できました。
「Link Binary With Libraries」に直接ドロップするのではなく、まずその下の「Copy Bundle Resources」にドロップしてから、そこから「Link Binary With Libraries」にドラッグ&ドロップするみたいですね。
その際、「Destination: Copy items if needed」にはチェック。
下の「Added folders:」では「Create groups」と「Create folder references」のどっちでも良さそうな気がしますが、とりあえず私は後者にしました。
実機でテストしても広告が表示されない
さて、エラーがなくなってアプリが実行されたとしても、テスト用のバナー広告は表示されるものの、実際の広告が表示されない。
これ私、仕組みがよくわかってなかったのですが、本番の広告はちゃんとApp申請してApp Storeに並んだ状態のアプリをダウンロードして実行しないと、表示されないんですね。
開発中でまだストアに並ぶ前のアプリでもちゃんと本物の広告が表示されるものだと思い込んでいたので、「なんでテスト用の広告は表示されるのに本番のバナー広告は表示されないんだー、これじゃアプリ申請できない」みたいな勘違いしていました。
だからテスト用のバナー広告が開発中に表示されているのを確認できればOKで、あとはそのテスト用バナー広告を表示するコードを削除してアプリ申請すればいいだけですね。
そしたら無事に最初の画像みたいに広告が表示されていました。
SpriteKit使っていてメイン画面をViewController.swiftじゃなくてGameScene.swiftとかの別ファイルでコーディングしているような場合であっても、ViewController.swift側に広告掲載のコードを書くことで無事に広告が表示されます。
最近のアプリの審査期間はものすごく早くて、バージョンアップ版を申請して1日以内に審査開始、審査完了がなされました。
広告ID(Advertising Identifier又はIDFA)で「はい」を選ぶ
これを忘れてはいけないのですが、「審査に提出」をクリックした後に表示される広告ID(Advertising Identifier又はIDFA)では「はい」を選択しなければなりません。
するとさらに質問項目が表示されて、「App内で広告を出す」とか「このAppのインストールを前に提供した広告と関連付ける」とか「このApp内で行われたアクションを前に提供した質問と関連付ける」とかへのチェックボックスが出るのですが、まあ基本的なバナー広告を表示するだけなら最初のボックスにチェックするだけで良いかと。
後、その下の「iOSの「追跡型広告を制限」設定」についても何かすごい誓いを行わなければならない感じの文章が記載されていますが、これもチェックしておきました。
これで問題なく審査通過してApp storeに並び、広告も表示されましたと。
XcodeのViewController.swiftでのコーディング(全画面広告、インタースティシャル広告)
次に全画面広告ですが、こちらはバナー広告よりも苦労しました。
アプリ起動時と終了時にインタースティシャル広告を出すのは規定上ルール違反らしいので、私のゲームアプリでゲームオーバーになったら広告を表示するようにしました。
ゲームオーバーになったことの罰ゲーム的な印象もあり、ゲームオーバーにならないようにする動機付けがプレイヤーに得られるとともに、ユーザーが負けたことでそうやって全画面広告を表示することは、ユーザー側の落ち度もあるということでそれほど嫌がられないかと。
import UIKit import GoogleMobileAds class ViewController: UIViewController, GADInterstitialDelegate { var _interstitial: GADInterstitial? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. ・・・ //広告 _interstitial = createAndLoadInterstitial() ・・・ }
GoogleMobileAdsをインポートしてGADInterstitialDelegateのデリゲートを導入しておくようにすることはバナー広告の時と同様。
次に変数の「_interstitial」を宣言してアプリ起動時に「createAndLoadInterstitial()」関数を呼び出して初期化しておく。
「createAndLoadInterstitial()」関数の中身は別途記述。
//広告 func createAndLoadInterstitial()->GADInterstitial { let interstitial = GADInterstitial(adUnitID: "ca-app-pub-***/***") interstitial.delegate = self let gadRequest:GADRequest = GADRequest() //gadRequest.testDevices = ["***"] // テスト時のみ interstitial.load(gadRequest) return interstitial }
次に、ゲームオーバー処理時に入れる処理。
presentInterstitial()//ゲームオーバー時
これで「presentInterstitial()」関数を呼び出す。
この処理は以下のようにする。
//広告 func presentInterstitial() { if let isReady = _interstitial?.isReady { _interstitial?.present(fromRootViewController: self) } }
com.apple.WebKit.WebContent drops 113 error: Could not find specified serviceとかGoogle Cannot present interstitial. It is not ready.の解決法
ここでバナー広告の時と違って、コードが間違っているわけではないのに、「com.apple.WebKit.WebContent drops 113 error: Could not find specified service」とか「
よくわからないので放置してしばらく待っていたりしたら、いつの間に勝手に解決されていました。
だから、これが表示されても落ち着いて対応していれば大丈夫です。多分。。。
Request Error: Will not send request because interstitial object has been usedの解決法
で、無事表示された後、2回目以降のゲームオーバー時にはなぜか広告が表示されなくなる現象に陥りました。
デバッグエリアのコンソールログには「Request Error: Will not send request because interstitial object has been used.」というメッセージが出ています。
これは上記参考にさせていただいたリンク先のサイトで「インタースティシャルを閉じたときの動作」というところがあったので、そこに以下の記述をしました。
func interstitialDidDismissScreen(_ ad: GADInterstitial!) { _interstitial = createAndLoadInterstitial() }
こちらのサイトによれば、インタースティシャル広告は一度呼び出してからまた呼び出したい場合には、再度初期化しなければならないらしいということです。
なので、また呼び出した後にアプリ起動時と同様の処理を書き、変数「_interstitial」を上書きしています。
これでエラーに対処できました。
なお、実際にクリックされて収益が発生している件は、iPhoneアプリでリジェクトされたのにAdMob広告収益が発生している件をご参照ください。