🍨

【Flutter】アプリ起動時広告を表示(AdMob)

2023/12/26に公開

はじめに

アプリ起動時広告ユニット

AdMobの「アプリ起動時広告ユニット」は、アプリを表示したりアプリに切り替えた時に画面を覆うように表示される広告のことです。

アプリ起動時広告ユニット

サンプルないの?

起動時/アプリ切り替え時以外は画面を邪魔することがないので導入したかったのですが、他広告ユニットのFlutterサンプルはあるのにアプリ起動時広告ユニットのサンプルがありませんでした。
他広告ユニットのサンプルを使えば書けるのですが、アプリ切り替え時にも表示するために少し調べたので、実装例を紹介したいと思います。
参考:
Flutterでの広告ユニット実装
Java/Kotlinでのアプリ起動時広告ユニット実装

実装例

Flutterバージョン

> flutter --version
Flutter 3.16.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 78666c8dc5 (7 days ago) • 2023-12-19 16:14:14 -0800
Engine • revision 3f3e560236
Tools • Dart 3.2.3 • DevTools 2.28.4
lib/main.dart
import 'package:flutter/material.dart';
+import 'package:flutter_application_1/appopen_admanager.dart';
+import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'アプリ起動時広告表示'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
+  AppOpenAdManager appOpenAdManager = AppOpenAdManager();
+  late final AppLifecycleListener _listener;

  
  void initState() {
+    appOpenAdManager.loadAd();
    _listener = AppLifecycleListener(
+      onShow: () => appOpenAdManager.loadAd(),
    );
    super.initState();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
/*  --- (略) --- */
    );
  }
}

途中で出てくるAppOpenAdManagerはこちら(https://qiita.com/celcior0913/items/ddbf25d7800d2f17839f)を引用させてもらいました。

引用した部分含めた差分(Android用)
android/app/build.gradle
plugins {
    id "com.android.application"
    id "kotlin-android"
    id "dev.flutter.flutter-gradle-plugin"
}
/*  --- (略) --- */
android {
    /*  --- (略) --- */
    defaultConfig {
-        minSdkVersion flutter.minSdkVersion
+        minSdkVersion 23
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }
    /*  --- (略) --- */
}

flutter {
    source '../..'
}

dependencies {
+    implementation 'com.google.android.gms:play-services-ads:22.6.0'
}
android/build.gradle
buildscript {
    ext.kotlin_version = '1.7.10'
    repositories {
+        google()
+        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
+        google()
+        mavenCentral()
    }
}
/*  --- (略) --- */
android/app/src/main/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application
        android:label="flutter_application_1"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
	/*  --- (略) --- */
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
+        <!-- テスト広告 -->
+        <meta-data
+            android:name="com.google.android.gms.ads.APPLICATION_ID"
+            android:value="ca-app-pub-3940256099942544~9257395921"/>
    </application>
</manifest>
lib/appopen_admanager.dart
import 'package:flutter_application_1/ad_helper.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

class AppOpenAdManager implements AppOpenAdLoadCallback {
  AppOpenAd? _appOpenAd;
  bool _isAdLoaded = false;

  void loadAd() {
    AppOpenAd.load(
      adUnitId: AdHelper.appopenAdUnitId,
      request: const AdRequest(),
      orientation: AppOpenAd.orientationPortrait,
      adLoadCallback: AppOpenAdLoadCallback(
        onAdLoaded: (ad) {
          _appOpenAd = ad;
          _isAdLoaded = true;
          _appOpenAd?.show();
        },
        onAdFailedToLoad: (error) {
          print('App open ad failed to load: $error');
        },
      ),
    );
  }

  void showAdIfLoaded() {
    if (_isAdLoaded) {
      _appOpenAd?.show();
    } else {
      loadAd();
    }
  }

  void onAppOpenAdLoaded(AppOpenAd ad) {
    _appOpenAd = ad;
    _isAdLoaded = true;
    showAdIfLoaded();
  }

  void onAppOpenAdFailedToLoad(LoadAdError error) {
    print('App open ad failed to load: $error');
  }

  void onAppOpenAdClosed() {
    _appOpenAd?.dispose();
    _isAdLoaded = false;
    loadAd();
  }

  void dispose() {
    _appOpenAd?.dispose();
  }

  
  // implement onAdFailedToLoad
  FullScreenAdLoadErrorCallback get onAdFailedToLoad => throw UnimplementedError();

  
  // implement onAdLoaded
  GenericAdEventCallback<AppOpenAd> get onAdLoaded => throw UnimplementedError();
}
lib/ad_helper.dart
import 'dart:io';

class AdHelper {
  static String get appopenAdUnitId {
    if (Platform.isAndroid) {
      // テスト広告
      return 'ca-app-pub-3940256099942544/9257395921';
    } else if (Platform.isIOS) {
      return 'ca-app-pub-3940256099942544/9257395921';
    } else {
      throw UnsupportedError('Unsupported platform');
    }
  }
}
pubspec.yaml
/*  --- (略) --- */
dependencies:
  flutter:
    sdk: flutter

+  google_mobile_ads:
/*  --- (略) --- */

起動時に広告表示するのは簡単で、MaterialApphomeに指定したWidgetのStateが初期化されるときに表示させれば良いです。

アプリが切り替わったときに表示するには、Flutter 3.13 から導入されたAppLifecycleListeneronRestartに広告表示の処理を記述してあげれば良いです。

https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html

おわりに

「アプリが切り替わった」などのライフサイクルをFlutterで扱うのはv3.13以前では少し面倒そうでした。。
AppLifecycleListenerばんざい。

Discussion