2021-03-04に更新

FlutterでAdMobのバナーをなんとかいい感じに使いこなす方法

FlutterにはAdMobを表示するパッケージがあるが、はっきり言って機能的にしょぼすぎて非常に使いづらい。もちろん独自に描画しているからうまく組み合わせることができないというのもあるのだろうが、それにしてもしょぼすぎて困る。

追記)公式でちゃんとしたやつが準備されているようです
https://crieit.net/posts/Flutter-AdMob-SDK

困るところ

いくつか困るところと試してみた改善方法。

位置もサイズもデフォルトだと辛い

一番困るのが、FloatingActionButtonとかぶるところ。右下に固定で表示されるボタンに広告かぶってしまって押すことができない。コンテンツとかぶるのでAdMobのポリシー違反扱いされる。

じゃあかぶらないように上にずらすか、と思うけれどもそもそも広告の高さが取得できない。まあこれはスマートバナーだとそもそも難しいのかもしれないけど。ということでサイズが必要な人は端末サイズに応じた普通のバナーを出すようにしているっぽい。

で、同じ様に使いづらい! と感じた方が位置などをカスタマイズできるパッケージを作ってくれているっぽい。

Flutterのfirebase_admobプラグインのバナー広告が使いにくいのでなんとかする - Qiita

ただまだできたばかりでちょこちょこエラーが出たりコンテンツにかぶったりする部分があるようで実用はできなそうだがとても期待。中のコードは参考になるので、バナーサイズの算出方法を参考にさせてもらっていい感じにフッターのバナーエリアのサイズを広告ぴったりにできるようにしたりしてみた。現時点(2021/1)ではdartファイルひとつなので見てみればすぐわかると思う。

参考にして下記のようなバナーのheightを算出する関数を作った。

double getBannerHeight(BuildContext context) {
  final _viewPaddingTop = WidgetsBinding.instance.window.viewPadding.top /
      MediaQuery.of(context).devicePixelRatio;
  final _viewPaddingBottom = WidgetsBinding.instance.window.viewPadding.bottom /
      MediaQuery.of(context).devicePixelRatio;
  final _screenWidth = MediaQuery.of(context).size.width;
  final _availableScreenHeight =
      MediaQuery.of(context).size.height - _viewPaddingTop - _viewPaddingBottom;
  if (_screenWidth >= 728 && _availableScreenHeight >= 720) {
    return 90;
  } else if (_screenWidth >= 468 && _availableScreenHeight >= 480) {
    return 60;
  } else if (_screenWidth >= 320 && _availableScreenHeight >= 700) {
    return 100;
  } else {
    return 50;
  }
}

同様にして、バナーのサイズ指定の値も。

AdSize getBannerAdSize(BuildContext context) {
  final _viewPaddingTop = WidgetsBinding.instance.window.viewPadding.top /
      MediaQuery.of(context).devicePixelRatio;
  final _viewPaddingBottom = WidgetsBinding.instance.window.viewPadding.bottom /
      MediaQuery.of(context).devicePixelRatio;
  final _screenWidth = MediaQuery.of(context).size.width;
  final _availableScreenHeight =
      MediaQuery.of(context).size.height - _viewPaddingTop - _viewPaddingBottom;

  if (_screenWidth >= 728 && _availableScreenHeight >= 720) {
    return AdSize.leaderboard;
  } else if (_screenWidth >= 468 && _availableScreenHeight >= 480) {
    return AdSize.fullBanner;
  } else if (_screenWidth >= 320 && _availableScreenHeight >= 700) {
    return AdSize.largeBanner;
  } else {
    return AdSize.banner;
  }
}

こんな感じで何にもかぶらないようにいい感じに表示できた。

文字入力時の考慮

ただ、文字入力をしようと思ってキーボードが表示された時に問題がある。というのも、この公式の広告はキーボードが表示されて画面が狭くなった時にはじゃまにならないように非表示になっている。ということで自分で表示したコンテナも非表示にしなければ入力時の画面がもっと狭くなってしまう。ということでそれはMediaQueryで判定できるらしい。

            Container(
              color: Colors.black,
              height: MediaQuery.of(context).viewInsets.bottom == 0
                  ? getBannerHeight(context) + 1
                  : 0,
            ),

バナーを切り替える機能がない

公式のドキュメントを見てもバナーを切り替える方法みたいなのが載ってない。

ページによって表示するバナーのサイズを変えたいという時があった。先程のように自動算出でなく、指定した大きさのものを出したい場合など。

ちゃっときりかえることはできなさそうで、dispose → load → show をその都度行う必要があるっぽい気がする。しかし、やってみるとエラーになったりする。load中に画面を切り替えてdisposeしてしまうと、そのあとshowを呼ばれるタイミングでエラーになる。

ということで公式に書いてある方法ではなく、下記のようにしたらdisposeしたものをshowしなくなった気がする。

    banner = BannerAd(
      adUnitId: getBannerId(),
      size: adSize,
      targetingInfo: targetingInfo,
      listener: (MobileAdEvent event) {
        if (event == MobileAdEvent.loaded) {
          banner.show(anchorType: AnchorType.bottom);
        }
      },
    );

ただしこれをすると単に広告を表示しているだけより、表示回数のカウントは増えるかもしれない。

まとめ

これで不便ながらもなんとか各ページごとにちょうど良いバナーを表示することができるようになった。とりあえずやってみたところなのでまだ何か問題が出るかもしれないが。

ツイッターでシェア
みんなに共有、忘れないようにメモ

だら@Crieit開発者

Crieitの開発者です。 Webエンジニアです(在宅)。大体10年ちょい。 記事でわかりにくいところがあればDMで質問していただくか、案件発注してください。 業務依頼、同業種の方からのコンタクトなどお気軽にご連絡ください。 業務経験有:PHP, MySQL, Laravel, React, Flutter, Vue.js, Node, RoR 趣味:Elixir, Phoenix, Nuxt, Express, GCP, AWS等色々 PHPフレームワークちいたんの作者

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント