インライン アダプティブ バナー

次世代のレスポンシブ広告であるアダプティブ バナーは、デバイスごとに広告サイズを最適化して広告の効果を高めます。アダプティブ バナーは固定サイズのバナーが改良されたもので、固定サイズのバナー広告の高さが固定されているのに対し、アダプティブ バナーではデベロッパーが指定する広告の幅に応じて、自動的に最適な広告サイズが決定されます。

最適な広告サイズが選択されるように、インライン アダプティブ バナーでは固定された高さではなく、最大高さが使用されます。これにより、広告の掲載結果の向上につながります。

インライン アダプティブ バナーの用途

インライン アダプティブ バナーは、アンカー アダプティブ バナーよりも大きく、高さのあるバナーです。インライン アダプティブ バナーでは高さが変動するため、デバイス画面と同じ大きさで表示できます。

次のような、スクロール型コンテンツに配置するためのものです。

前提条件

始める前に

アプリにアダプティブ バナーを実装する際には、次の点に注意してください。

  • 使用する Google Mobile Ads SDK が最新バージョンであることを確認し、メディエーションを使用する場合には、最新バージョンのメディエーション アダプタを使用してください。

  • インライン アダプティブ バナーは、利用できるスペースの横幅いっぱいに表示すると最も効果を発揮するように設計されています。ほとんどの場合は、デバイスの画面の全幅を使用できます。セーフエリアがある場合は、そのスペースも考慮に入れてください。

  • 広告サイズを取得する方法は次のとおりです。

    • AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(int width)
    • AdSize.getLandscapeInlineAdaptiveBannerAdSize(int width)
    • AdSize.getPortraitInlineAdaptiveBannerAdSize(int width)
    • AdSize.getInlineAdaptiveBannerAdSize(int width, int maxHeight)
  • インライン アダプティブ バナー API を使用している場合、Google Mobile Ads SDK は指定された幅とインライン フラグが設定された AdSize を返します。高さは、使用している API に応じて 0 または maxHeight になります。広告の実際の高さは、返された値で確認できます。

  • インライン アダプティブ バナーは、スクロール可能なコンテンツに配置されるよう設計されています。バナーの高さは、API に応じて、デバイス画面と同じ大きさか、最大高さの制限値となります。

実装

シンプルなインライン アダプティブ バナーを実装する手順は次のとおりです。

  1. インライン アダプティブ バナーの広告サイズを取得します。取得したサイズは、アダプティブ バナーのリクエストに使用します。アダプティブ バナーの広告サイズを取得するには、次の手順を行ってください。
    1. 広告を掲載するデバイスの幅を密度非依存ピクセルで取得します。デバイス画面の幅全体を使用しない場合は、任意の幅を設定します。MediaQuery.of(context) を使用して、画面の幅を取得します。
    2. 広告サイズクラスの適切な静的メソッド(AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(int width) など)を使用して、指定した向きのインライン アダプティブ バナーの AdSize オブジェクトを取得します。
    3. バナーの高さを制限する場合は、静的メソッド AdSize.getInlineAdaptiveBannerAdSize(int width, int maxHeight) を使用します。
  2. 広告ユニット ID、アダプティブ バナーのサイズ、広告リクエスト オブジェクトを設定して BannerAd オブジェクトを作成します。
  3. 広告を読み込みます。
  4. onAdLoaded コールバックで、BannerAd.getPlatformAdSize() を使用して、更新されたプラットフォーム広告サイズを取得し、AdWidget コンテナの高さを更新します。

サンプルコード

インセットを考慮した画面の幅に合わせて、インライン アダプティブ バナーを読み込むウィジェットの例を次に示します。

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

/// This example demonstrates inline adaptive banner ads.
///
/// Loads and shows an inline adaptive banner ad in a scrolling view,
/// and reloads the ad when the orientation changes.
class InlineAdaptiveExample extends StatefulWidget {
  @override
  _InlineAdaptiveExampleState createState() => _InlineAdaptiveExampleState();
}

class _InlineAdaptiveExampleState extends State<InlineAdaptiveExample> {
  static const _insets = 16.0;
  BannerAd? _inlineAdaptiveAd;
  bool _isLoaded = false;
  AdSize? _adSize;
  late Orientation _currentOrientation;

  double get _adWidth => MediaQuery.of(context).size.width - (2 * _insets);

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _currentOrientation = MediaQuery.of(context).orientation;
    _loadAd();
  }

  void _loadAd() async {
    await _inlineAdaptiveAd?.dispose();
    setState(() {
      _inlineAdaptiveAd = null;
      _isLoaded = false;
    });

    // Get an inline adaptive size for the current orientation.
    AdSize size = AdSize.getCurrentOrientationInlineAdaptiveBannerAdSize(
        _adWidth.truncate());

    _inlineAdaptiveAd = BannerAd(
      // TODO: replace this test ad unit with your own ad unit.
      adUnitId: 'ca-app-pub-3940256099942544/9214589741',
      size: size,
      request: AdRequest(),
      listener: BannerAdListener(
        onAdLoaded: (Ad ad) async {
          print('Inline adaptive banner loaded: ${ad.responseInfo}');

          // After the ad is loaded, get the platform ad size and use it to
          // update the height of the container. This is necessary because the
          // height can change after the ad is loaded.
          BannerAd bannerAd = (ad as BannerAd);
          final AdSize? size = await bannerAd.getPlatformAdSize();
          if (size == null) {
            print('Error: getPlatformAdSize() returned null for $bannerAd');
            return;
          }

          setState(() {
            _inlineAdaptiveAd = bannerAd;
            _isLoaded = true;
            _adSize = size;
          });
        },
        onAdFailedToLoad: (Ad ad, LoadAdError error) {
          print('Inline adaptive banner failedToLoad: $error');
          ad.dispose();
        },
      ),
    );
    await _inlineAdaptiveAd!.load();
  }

  /// Gets a widget containing the ad, if one is loaded.
  ///
  /// Returns an empty container if no ad is loaded, or the orientation
  /// has changed. Also loads a new ad if the orientation changes.
  Widget _getAdWidget() {
    return OrientationBuilder(
      builder: (context, orientation) {
        if (_currentOrientation == orientation &&
            _inlineAdaptiveAd != null &&
            _isLoaded &&
            _adSize != null) {
          return Align(
              child: Container(
            width: _adWidth,
            height: _adSize!.height.toDouble(),
            child: AdWidget(
              ad: _inlineAdaptiveAd!,
            ),
          ));
        }
        // Reload the ad if the orientation changes.
        if (_currentOrientation != orientation) {
          _currentOrientation = orientation;
          _loadAd();
        }
        return Container();
      },
    );
  }

  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(
        title: Text('Inline adaptive banner example'),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: _insets),
          child: ListView.separated(
            itemCount: 20,
            separatorBuilder: (BuildContext context, int index) {
              return Container(
                height: 40,
              );
            },
            itemBuilder: (BuildContext context, int index) {
              if (index == 10) {
                return _getAdWidget();
              }
              return Text(
                'Placeholder text',
                style: TextStyle(fontSize: 24),
              );
            },
          ),
        ),
      ));

  @override
  void dispose() {
    super.dispose();
    _inlineAdaptiveAd?.dispose();
  }
}