[Flutter]バナー広告をWidgetに埋め込む

# はじめに
先日、[AppStore](https://itunes.apple.com/jp/app/id1474327443?mt=8)と[GooglePlayStore](http://play.google.com/store/apps/details?id=net.loosespace.easier)でEASIERを公開しました。
![1024_500.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413778/05f4ca2b-f04d-f4dd-f86c-cdd14b133a89.jpeg)

これは、障がい者の方による障がい者のためのニュースアプリとしてリリースしました。
このプロジェクトではマネタイズが一つのポイントとしてあって、
障がいがある方達がライターとして参加することで、一つの職として生計を立てていけるようなモデルを目指しています。

その中で、広告モデルを取り入れたのですが
Flutterで広告を表示するためにいくつか調べてる中で、良さげな物を見つけたのでまとめておきます。


# アプリ内広告
アプリのマネタイズ方法はいくつかあり、その1つがアプリ内に表示される広告になります。
Flutterに公式プラグインとして[firebase_admob](https://pub.dev/packages/firebase_admob)があるのですが、広告は全てオーバーレイで全てのWidgetの上に表示されたり
バナーの位置が、上下からしか配置できないなどいくつかの制約がありました。

そこで、色々と調べてみると[admob_flutter](https://pub.dev/packages/admob_flutter#-readme-tab-)というものを見つけました。
admob_flutterは公式とことなり、Widget内に埋め込むことができデザインを壊さずに広告を表示できるプラグインです。

ただ、開発者は新しいメンテナーを探しており、更新があまり行われていないため
組み込む場合は検討が必要となります。

# プロジェクト作成
まずは、プラグインを使用するためにシンプルなアプリを作成します。

```console
flutter create admob_test
```

```dart:lib/main.dart
import 'package:flutter/material.dart';

void main() {
 runApp(Application());
}



class Application extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: "Admob test",
     home: Scaffold(
       appBar: AppBar(
         title: Text("Flutter admob test"),
       ),
       body: Container(),
     ),
   );
 }
}
```

プラグインを使用するために、`pubspec.yaml`に依存関係を追加していきます。

```yaml:pubspec.yaml
# ...
dependencies:
 flutter:
   sdk: flutter
 admob_flutter: ^0.3.1
 # other dependencies
# ...
```

## Androidの設定
`AndroidManifest.xml`にadmobのidを追加していきます。

``` xml:android/app/src/main/AndroidManifest.xml
<meta-data
 android:name="com.google.android.gms.ads.APPLICATION_ID"
 android:value="ca-app-pub-3940256099942544~3347511713"/>
```

<img width="1011" alt="スクリーンショット 2019-08-13 16.15.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413778/8160b73b-191c-6d8b-de5e-408ce8813ee4.png">

## iOSの設定
iOSでは`Info.plist`にキーを追加していきます。

```text:ios/Runner/Info.Plist
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>io.flutter.embedded_views_preview</key>
<true/>
```

<img width="819" alt="スクリーンショット 2019-08-13 16.20.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413778/cf92c68f-ce09-89d8-d4e2-519b6ad15054.png">

# 広告の表示
ここまでで、準備は完了したので実際にアプリ内に広告を表示させていきます。

![Simulator Screen Shot - iPhone Xʀ - 2019-08-13 at 17.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413778/9877399f-26e3-4231-b290-6aa21ec05be8.png)
このように、リストの途中に表示できるようにしていきます。
まずは、admobのアプリIDを使用して初期化を行なっていきます。
### 初期化

```dart
import 'package:flutter/material.dart';
import 'package:admob_flutter/admob_flutter.dart';
import 'dart:io';

void main() {
  Admob.initialize(getAppId());
  runApp(Application());
}


String getAppId() {
  if (Platform.isIOS) {
    return 'ca-app-pub-3940256099942544~1458002511';
  } else if (Platform.isAndroid) {
    return 'ca-app-pub-3940256099942544~3347511713';
  }
  return null;
}
```

OSごとに異なるアプリIDになると思うので、ios/androidを判別してアプリIDを返す`getAppId`関数を作成し
main関数で初期化を行います。

このときに`io`と`admob_flutter`のimportを忘れないようにしましょう。

### 組み込み

```dart

  Widget _buildListView() {
    final int size = 10;
    List<Widget> _children = List<Widget>.generate(
      size,
      (int index) => _buildListItem(text: "iTem: $index"),
    );
    return ListView(
      children: _children,
    );
  }

  Widget _buildListItem({String text}) {
    return Container(
      height: 150,
      child: Card(
        color: Colors.grey,
        child: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Center(child: Text(text)),
        ),
      ),
    );
  }
}
```

これは、緑のCardを10個のリストとして、返す関数を作成しています。
本題とはずれるので特に解説はしません。


```dart
  Widget _buildListView() {
    final int size = 10;
    List<Widget> _children = List<Widget>.generate(
      size,
      (int index) => _buildListItem(text: "iTem: $index"),
    );

    _children.insert(
      2,
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: AdmobBanner(
          adUnitId: getBannerAdUnitId(),
          adSize: AdmobBannerSize.LEADERBOARD,
        ),
      ),
    );

    return ListView(
      children: _children,
    );
  }
```
getBannerAdUnitId関数を作成して`insert`文で3番目に追加していきます。

```dart
String getBannerAdUnitId() {
  if (Platform.isIOS) {
    return 'ca-app-pub-3940256099942544/2934735716';
  } else if (Platform.isAndroid) {
    return 'ca-app-pub-3940256099942544/6300978111';
  }
  return null;
}
```

```dart
  Widget _buildListView() {
    final int size = 10;
    List<Widget> _children = List<Widget>.generate(
      size,
      (int index) => _buildListItem(text: "iTem: $index"),
    );
    // ここに追加
    _children.insert(
      2,
      Padding(
        padding: const EdgeInsets.all(8.0),
        child: AdmobBanner(
          adUnitId: getBannerAdUnitId(),
          adSize: AdmobBannerSize.LEADERBOARD,
        ),
      ),
    );

    return ListView(
      children: _children,
    );
  }
```

これでリストの中に、広告を表示させる処理が完成しました。
あとは、build関数のbodyを書き換えるだけで完成です。

```dart
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Admob test",
      home: Scaffold(
        appBar: AppBar(
          title: Text("Flutter admob test"),
        ),
        body: _buildListView(),
      ),
    );
  }
```

# おわりに
以上で、Widget内にadmob広告を埋めれるようになります。
冒頭でも言った通り、現在メンテナーを探しているようです。
これに魅力を感じ、我こそは。って方がいらっしゃいましたらよろしくお願いします。

修正点等ありましたら、ご指摘お願いします。