🦁

Flutterでバナー広告とインタースティシャル広告を実装する

2023/05/10に公開1

Flutter/Dartで基本的な広告であるバナー広告とインタースティシャル広告を実装します!

画面下部に固定でバナー広告を
ボタン10回押すたびにインタースティシャル広告を表示するような実装になります!

インポート

pubspec.yamlファイルにgoogle_mobile_adsのインポートを追加

dev_dependencies:
  flutter_test:
    sdk: flutter

  google_mobile_ads: ^2.4.0

各OSごとの設定

chatGPTからいただいたありがたい内容のまんま。

○Androidの場合

android/app/src/main/AndroidManifest.xmlファイルに以下のメタデータを追加します。

AndroidManifest.xml
<application>
   <!-- AdMobアプリIDをここに追加します -->
   <meta-data
       android:name="com.google.android.gms.ads.APPLICATION_ID"
       android:value="ca-app-pub-################~##########"/>
</application>

◯iOSの場合

ios/Runner/Info.plistファイルに以下のエントリを追加します。

Info.plist
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-################~##########</string>
<key>io.flutter.embedded_views_preview</key>
<true/>

ファイル構成

画像参照

AdBanner.dart……………………バナー広告の実装ファイル
AdInterstitial.dart………………インタースティシャル広告の実装ファイル
AdManager.dart…………………広告関連全般を扱うファイル
main.dart………………………………説明不要!!

各ファイルの実装

AdManager.dart

Android/iOSでそれぞれのアプリID,広告IDをこのファイルで一元管理!!

AdManager.dart

import 'dart:io';

class AdManager {
  // アプリIDを返す関数
  static String get appId {
    if (Platform.isAndroid) {
      return "AndroidのアプリID";
    } else if (Platform.isIOS) {
      return "iOSのアプリID";
    } else {
      throw UnsupportedError("Unsupported platform");
    }
  }

  // バナー広告ユニットIDを返す関数
  static String get bannerAdUnitId {
    if (Platform.isAndroid) {
      return "ca-app-pub-3940256099942544/6300978111"; // テストID
    } else if (Platform.isIOS) {
      return "ca-app-pub-3940256099942544/6300978111"; // テストID
    } else {
      throw UnsupportedError("Unsupported platform");
    }
  }

  // インターステシャル広告ユニットIDを返す関数
  static String get interstitialAdUnitId {
    if (Platform.isAndroid) {
      return "ca-app-pub-3940256099942544/1033173712"; // テストID
    } else if (Platform.isIOS) {
      return "ca-app-pub-3940256099942544/1033173712"; // テストID
    } else {
      throw UnsupportedError("Unsupported platform");
    }
  }

}

AdBanner.dart

バナー広告のファイル

AdBanner.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'AdManager.dart';

/// バナー広告用の管理用クラス
class AdBanner {
  // バナー広告を作成
  static BannerAd createBannerAd() {
    return BannerAd(
      adUnitId: AdManager.bannerAdUnitId,
      size: AdSize.fullBanner,
      request: const AdRequest(),
      listener: BannerAdListener(
        onAdLoaded: (Ad ad) => print('バナー広告がロードされました'),
        onAdFailedToLoad: (Ad ad, LoadAdError error) {
          ad.dispose();
          print('バナー広告の読み込みが次の理由で失敗しました: $error');
        },
        onAdOpened: (Ad ad) => print('バナー広告が開かれました'),
        onAdClosed: (Ad ad) => print('バナー広告が閉じられました'),
        onAdImpression: (Ad ad) => print('次のバナー広告が表示されました: $ad'),
      ),
    );
  }
}

AdInterstitial.dart

インタースティシャル広告のファイル。ほぼAdBannerと一緒。

AdBanner.dart
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'AdManager.dart';

/// バナー広告用の管理用クラス
class AdBanner {
  // バナー広告を作成
  static BannerAd createBannerAd() {
    return BannerAd(
      adUnitId: AdManager.bannerAdUnitId,
      size: AdSize.fullBanner,
      request: const AdRequest(),
      listener: BannerAdListener(
        onAdLoaded: (Ad ad) => print('バナー広告がロードされました'),
        onAdFailedToLoad: (Ad ad, LoadAdError error) {
          ad.dispose();
          print('バナー広告の読み込みが次の理由で失敗しました: $error');
        },
        onAdOpened: (Ad ad) => print('バナー広告が開かれました'),
        onAdClosed: (Ad ad) => print('バナー広告が閉じられました'),
        onAdImpression: (Ad ad) => print('次のバナー広告が表示されました: $ad'),
      ),
    );
  }
}

main.dart

実際に実装するのはここ。

main.dart
class _MyHomePageState extends State<MyHomePage> {

  /// バナー広告を作成
  BannerAd bannerAd = AdBanner.createBannerAd();

  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;

      if(_counter % 10 == 0) {
        // 10の倍数の場合に広告表示する
        AdInterstitial.showInterstitialAd();
      }

    });
  }

  
  Widget build(BuildContext context) {

    /// バナー広告ウィジェットを作成
    final AdWidget bannerAdWidget = AdWidget(ad: bannerAd);

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(children: [
        Expanded(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headlineMedium,
              ),
            ],
          ),
        ),

    Container(
          alignment: Alignment.center,
          width: bannerAd.size.width.toDouble(),
          height: bannerAd.size.height.toDouble(),
          child: bannerAdWidget,
        ),
      ])),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  
  void initState() {
    super.initState();

    /// 広告読込
    /// インターステシャル広告を作成
    AdInterstitial.createInterstitialAd();

    // 以下URLのエラー回避のためにinitStateで読込実行する必要がある
    // https://stackoverflow.com/questions/71104572/how-to-fix-the-issue-ad-load-to-be-called-before-adwidget-is-inserted-into-the
    bannerAd.load();
  }

}

実装の注意点

initStateのタイミングで
・インタースティシャル広告を作成
・バナー広告の読込
をする必要がある。
そうしないと広告が読み込まれる前に起動しようとして、赤い画面表示になるので注意。

画面表示

画面はAndroidですが、iOSも同様に実装確認はできました!

↓もう1回押下

まとめ

広告関連は表示の実装よりAdmob設定やFirebaseの設定の方が大変よね。。

Arsaga Developers Blog

Discussion

たつきたつき

要修正
インタースティシャル広告のファイルの中身がバナー広告になっている