SwiftUIでリワード広告

SwiftUIアプリにリワード広告を実装しました。
この間とりあえずで実装したもの↓↓を修正しました。

Google-Mobile-Ads-SDK 8.0以降対応です(GADFullScreenContentDelegate使用)

import GoogleMobileAds

class RewardedAd: NSObject, GADFullScreenContentDelegate, ObservableObject {
    
    enum AdStatus{
        case loading
        case loaded
        case playing
        case played
        case failed
    }
    
    var resultObject:ResultObject //結果受け取り用、こいつの関連は好きにやってください    
    var rewardedAd: GADRewardedAd?

    @Published var adStatus = AdStatus.loading

    init(resultObject:ResultObject){
        self.resultObject = resultObject
        
        super.init()
        
        self.adLoad()
    }
    
    func adLoad(){
     self.adStatus = .loading

        let request = GADRequest()
        
        GADRewardedAd.load(withAdUnitID: "ca-app-pub-3940256099942544/1712485313" // テストID
                           ,request: request ){ (rewardedAd, error) in
            if let error = error {
                print(error.localizedDescription)
                self.adStatus = .failed
                return
            }
            self.rewardedAd = rewardedAd
            self.rewardedAd?.fullScreenContentDelegate = self
            self.adStatus = .loaded
        }
    }
    
    
    // 広告を表示して報酬を獲得する
    func showRewardedAd() {
        guard let root = UIApplication.shared.windows.first?.rootViewController else {
            return
        }
        self.showRewardedAd(viewController: root)
    }
    
    // 単純なSwiftUIアプリなら上のに統合して良い筈。
    func showRewardedAd(viewController:UIViewController) {
        if let rewardedAd = self.rewardedAd {
            rewardedAd.present(fromRootViewController: viewController,
                       userDidEarnRewardHandler: {
               //報酬獲得時の動作
                        self.resultObject.isRewarded = true
                    }
            )
        } else {
            print("Ad wasn't ready")
        }
    }
    
    // 広告表示時
    func adDidPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
        self.adStatus = .playing
    }
    
    // 広告クローズ時、報酬獲得の有無は関係なし
    func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
        // 再生中に閉じられたら広告の再ロードが必要
        if self.adStatus == .playing {
            self.adLoad()
        }
    }
    
    // 広告表示失敗時
    func ad(_ ad: GADFullScreenPresentingAd ,didFailToPresentFullScreenContentWithError error: Error) {
        print(error.localizedDescription)
        self.adStatus = .failed
    }
    
}

ResultObjectについてはtrue/falseを外部に渡す為だけなので省略します。
後でRewardedAdから直接読み取るなら適当な変数でもいいですし、
staticな変数に渡すならそもそもRewardedAd内に持つ必要もないです。

以下おまけのView

struct RewardAdView:View {
    
    @ObservedObject var rewardedAd:RewardedAd
    
    init(resultObject:ResultObject){
        self.rewardedAd = RewardedAd(resultObject:ResultObject)
    }
    
    var body: some View{
        VStack {
            Spacer()
            if self.rewardedAd.adStatus == .loaded {
                Button(action: {
                    self.rewardedAd.showRewardedAd()
                }, label: {
                    Text("広告を再生する")
                })
            }else if self.rewardedAd.adStatus == .loading {
                Text("広告読み込み中")
            }else if self.rewardedAd.adStatus == .played {
                Text("報酬を獲得しました")
            }else{
                Button(action: {
                    self.rewardedAd.adLoad()
                }, label: {
                    Text("広告のロードに失敗しました。\nタップで広告を再読み込みします。")
                        .multilineTextAlignment(.center)
                })
            }
            Spacer()
        }

    }
}

.playingの時は広告で隠れて見えないので気にしてないです。
このViewは実際に使ってる所と違うのでかなり適当です。

公式ドキュメントが何故かObjective-Cだったり(8.0.0未満はSwiftのコードもある)、
Google Mobile Ads SDK 8.0.0未満の記事だとGADRewardedAdDelegateだったり、
いくつか最近の記事を漁ったもののしっくり来なかったので自己流にアレンジしました。

コメント

タイトルとURLをコピーしました