えいむーさんは明日も頑張るよ

GoogleMobileAdsをiOSアプリに組み込む

価格

GoogleMobileAds

必要なもの

広告ユニットの作成

広告ユニットを作成すると二つの ID が生成されます。

// 共通ID [Info.plist]
ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY
// ユニットID [View]
ca-app-pub-XXXXXXXXXXXXXXXX/YYYYYYYYYY

一方がそのアプリで唯一の ID で、もう一方はユニット ID です。ここでは仮に共通 ID、ユニット ID と呼ぶことにします。

共通 ID はInfo.plistに書き込みますが、Info.plistは記述がいっぱいあるのでまとめておきましょう。

コード

ここからは実際に Xcode 上で作業をしていきます。

Other Linker Flags

TARGETS -> Build Settings -> Other Linker Flags-Objcと書かなければいけないと書いてあるドキュメントがありますが、自分の場合は何故か不要でした、何故なのかはわからないです。

Info.plist

Info.plistには共通 ID を書き込みます。

Key Type Value
Privacy - Tracking Usage Description String NSUserTrackingUsageDescription
GADApplicationIdentifier String ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY
GADIsAdManagerApp Boolean 1
SKAdNetworkItems Array

公式ドキュメントにも書いていないのですが、GADIsAdManagerAppを書き込まないとアプリがクラッシュします。

SKAdNetworkIdentifierは iOS14 以降で IDFA を利用する場合にユーザ許可が必要になったのでこれで対応しないといけません。

Privacy - Tracking Usage Descriptionは IDFA のダイアログが表示されたときのメッセージの内容です。今回は適当にNSUserTrackingUsageDescriptionとしていますが、これは後述する複数言語に対応する場合のための書き方です。日本語だけしか対応する予定がないなら、ここの値は決め打ちでも構いません。

SKAdNetworkItemsには次の値を書き込みます。

<key>SKAdNetworkItems</key>
  <array>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>cstr6suwn9.skadnetwork</string>
    </dict>
  </array>

View の作成

GoogleMobileAds は SwiftUI に直接対応していないので、UIViewControllerRepresentableを使って SwiftUI でも使えるようにします。

import SwiftUI
import GoogleMobileAds

internal struct UIGoogleMobileAds: UIViewControllerRepresentable {
    func makeUIViewController(context: Context) -> UIViewController {
        GADMobileAds.sharedInstance().start(completionHandler: nil)

        let view = GADBannerView(adSize: GADAdSizeBanner)
        let viewController = UIViewController()
        #if DEBUG
        // 自分のユニットID
        view.adUnitID = ""
        #else
        // テスト用のユニットID
        view.adUnitID = "ca-app-pub-7107468397673752/9251240303"
        #endif
        view.rootViewController = viewController
        viewController.view.addSubview(view)
        viewController.view.frame = CGRect(origin: .zero, size: GADAdSizeBanner.size)
        view.load(GADRequest())
        return viewController
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}

struct GoogleMobileAds: View {
    var body: some View {
        UIGoogleMobileAdsView()
            .frame(width: 320, height: 50)
    }
}

自分で自分の広告を表示させたりクリックしたりすると不正なトラフィックとして最悪、BAN されてしまうのでデバッグビルドではテスト用の広告を表示させるようにしましょう。

IDFA のダイアログ

最後に、IDFA の許可を求めるダイアログが表示されるようにします。

これをしないと審査で「どこでダイアログでてるの」とツッコまれます。

import SwiftUI
import Firebase
import AppTrackingTransparency
import GoogleMobileAds

@main
struct SampleApp: App {
    // AppDelegateを追加
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class SceneDelegate: NSObject, UIWindowSceneDelegate {
    func sceneDidBecomeActive(_ scene: UIScene) {
        /// IDFA対応の広告表示
        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
            if #available(iOS 14.5, *) {
                ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
                    GADMobileAds.sharedInstance().start(completionHandler: nil)
                })
            } else{
                GADMobileAds.sharedInstance().start(completionHandler: nil)
            }
        })
    }
}

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        // Firebaseの初期化
        FirebaseApp.configure()
        return true
    }

    func applicationDidFinishLaunching(_ application: UIApplication) {
    }

    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        let sceneConfig = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
        sceneConfig.delegateClass = SceneDelegate.self
        return sceneConfig
    }

    func applicationWillTerminate(_ application: UIApplication) {
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
}

iOS14?だと起動直後にダイアログを出そうとするとでてこなくて困ってしまうので、sceneDidBecomeActiveが呼ばれてからダイアログを表示するようにします。

こうすることで、初回起動時の最初の一回だけこのダイアログが表示されます。

許可した場合には IDFA を利用した広告、そうでない場合は Apple が指定した広告が表示されます。

記事は以上。

価格
    えいむーさんは明日も頑張るよ © 2022