事前準備
- AdMobアカウントを作成済み
- AdMobにアプリを登録していること
なお、記事内の広告テスト用IDを使えば試すだけなら可能。
環境
- iOS13.6.1
- Google-Mobile-Ads-SDK 7.64.0
- CocoaPods 1.9.3
- Xcode 11.6
ATSを設定
App Transport Security | iOS | Google Developers
ATSを切る、つまり安全でない通信やHTTP通信をすべて許可に設定する
info.plistに以下を追加
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
注意
Googleのドキュメントには
NSAllowsArbitraryLoadsInWebContentとNSAllowsArbitraryLoadsForMediaもTrueで追加する設定がある。
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsArbitraryLoadsForMedia</key>
<true/>
しかしこの通り設定したところ、iOS13では広告をタップして遷移した際に
Cannot start load of Task XXXXXXX since it does not conform to ATS policy
エラーが発生。(広告ランディングページへの遷移自体には問題なかった)
これは、NSAllowsArbitraryLoads以外の値を設定すると、「ATS全て許可」設定が無視されてしまう仕様によるもの。
- NSAllowsArbitraryLoadsInWebContent: WebViewでの通信のみATSを切る。他はATSオン。
- NSAllowsArbitraryLoadsForMedia: リモート上のメディアへの通信のみATSを切る。他はATSオン
つまり、他のすべての通信はATSオン状態なので、Googleが裏でやっている通信が全てブロックされている状況。
NSAllowsArbitraryLoadsInWebContentとNSAllowsArbitraryLoadsForMediaは削除し、
NSAllowsArbitraryLoadsのみをTrueで設定したところ、このエラーは消えた。
AdMob SDKのインストール
CocoaPodsを使った方法を推奨とのこと。
Podfileに以下を追加して
pod 'Google-Mobile-Ads-SDK'
インストール実行。
pod install
AdMob アプリIDの設定
info.plistに以下を追加
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
ちなみにこの
ca-app-pub-3940256099942544~1458002511
はテスト用のAdMobアプリID。試したいだけであればこのIDでSDKを初期化が可能。
本番時は、AdMobの管理画面から取得したIDを設定する。
ちなみに、このIDをinfo.plistに設定し忘れるとクラッシュするとのこと。
AdMobを初期化
**GADMobileAds
のインスタンスメソッド、start(completionHandler:)
**を呼び出して初期化。
初期化が完了(または30秒タイムアウト)すると、**completionHandler
**が呼ばれる。
この初期化処理は
-
1回だけ
-
アプリの起動時が理想的
-
できるだけ早く呼び出す
というのが推奨されるとのこと。
以下は、AppDelegate
のapplication(_:didFinishLaunchingWithOptions:)
で初期化するパターン
import GoogleMobileAds // AdMobのインポート
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GADMobileAds.sharedInstance().start { (status) in
// 初期化が完了(or タイムアウト)
debugPrint("AdMob Initialization Completed")
for (k,v) in status.adapterStatusesByClassName {
debugPrint("\(k) >> \(v.state.rawValue == 1 ? "Ready" : "NotReady")")
}
}
}
デバッグエリアにこの様に出れば初期化成功。
AdMob Initialization Completed
GADMobileAds >> Ready
広告の表示
今回は、UIの変更が少なくて済むインタースティシャル広告を使って表示テスト。
- インタースティシャル広告: 画面遷移時の途中などで全画面表示されるタイプの広告
まず、広告オブジェクトを初期化
広告オブジェクト**GADInterstitial
**を広告ユニットIDで初期化。
let interstitial = GADInterstitial(adUnitID: "ca-app-pub-3940256099942544/4411468910")
// はテスト専用ID
この**ca-app-pub-3940256099942544/4411468910
**は、テスト専用のインタースティシャル広告ユニットID。
なお
アプリの開発とテストでは実際の広告ではなく、必ずテスト広告を使ってください。実際の広告でテストすると、アカウントが停止される可能性があります。
と言うことなので、テスト時には必ずテスト用の広告ユニットIDが指定される様に実装すること。
次に、広告を読み込む
リクエストオブジェクトGADRequest
のインスタンスを作成して、広告を事前にロードしておく。
interstitial.load(GADRequest())
そして、広告を表示
表示する直前でも、GADInterstitial
の**isReady
**で表示可能かどうかをチェックしてから、
同じくGADInterstitial
のインスタンスメソッド、present(fromRootViewController:)
で表示します
guard interstitial.isReady else {
debugPrint("Interstitial Ad is NOT Available")
return
}
interstitial.present(fromRootViewController: self)
留意点
-
GADInterstitialのインスタンスは、一度広告表示したら使い捨てる
-
初期化とリロードは**
GADInterstitialDelegate
のfunc interstitialDidDismissScreen(_ :)
**でやる
ViewControllerに実装
import UIKit
import GoogleMobileAds
class SomeViewController: UIViewController {
var interstitialAd: GADInterstitial?
override func viewDidLoad() {
super.viewDidLoad()
interstitialAd = loadInterstitialAd()
}
@IBAction fileprivate func someAction(){
showInterstitialAd()
}
}
extension SomeViewController: GADInterstitialDelegate {
// 広告オブジェクトの生成とロード
fileprivate func loadInterstitialAd() -> GADInterstitial {
let interstitial = GADInterstitial(adUnitID: interstitialAdID)
interstitial.delegate = self
interstitial.load(GADRequest())
return interstitial
}
// 広告を表示
fileprivate func showInterstitialAd(){
guard let _ad = interstitialAd, _ad.isReady else {
debugPrint("Interstitial Ad Does NOT Available")
return
}
_ad.present(fromRootViewController: self)
}
// 広告を見せた後のスキームの再開
fileprivate func resumeSuspendedUserScheme(){
debugPrint("Resume suspended user scheme")
}
//MARK: GADInterstitialDelegate
/// Tells the delegate an ad request succeeded.
func interstitialDidReceiveAd(_ ad: GADInterstitial) {
debugPrint("interstitial Did ReceiveAd")
}
/// Tells the delegate an ad request failed.
func interstitial(_ ad: GADInterstitial, didFailToReceiveAdWithError error: GADRequestError) {
debugPrint("interstitial:didFailToReceiveAdWithError: \(error.localizedDescription)")
}
/// Tells the delegate that an interstitial will be presented.
func interstitialWillPresentScreen(_ ad: GADInterstitial) {
debugPrint("interstitial Will PresentScreen")
}
/// Tells the delegate the interstitial is to be animated off the screen.
func interstitialWillDismissScreen(_ ad: GADInterstitial) {
debugPrint("interstitial Will Dismiss Screen")
}
/// Tells the delegate the interstitial had been animated off the screen.
func interstitialDidDismissScreen(_ ad: GADInterstitial) {
debugPrint("interstitial Did Dismiss Screen")
interstitialAd = loadInterstitialAd()
resumeSuspendedUserScheme()
}
/// Tells the delegate that a user click will open another app
/// (such as the App Store), backgrounding the current app.
func interstitialWillLeaveApplication(_ ad: GADInterstitial) {
debugPrint("User Click Ad")
debugPrint("interstitial Will Leave Application")
}
}