Flutterのネイティブ広告をKotlinで実装する
先日、Google Mobile Adsのflutterプラグインが発表されました。先祖のプラグインにあたるAdmobは非常に使いづらかった印象だったので、ついにきたか!と非常にわくわくしました。
はじめに
先日、Google Mobile Adsのflutterプラグインが発表されました。
ネイティブ | Flutter(ベータ版) | Google Developers
先祖のプラグインにあたるAdmobは非常に使いづらかった印象だったので、ついにきたか!と非常にわくわくしました。 早速実装をしようと以下の公式docを参照してみたのですが、ネイティブ広告のAndroidのサンプルコードがjavaでした。
私が開発中のプロダクトはKotlinを採用しているので、公式サンプルをKotlinに読み替えつつ、ネイティブ広告の実装方法を共有したいと思います。
サンプル
今回紹介するサンプルは以下のリポジトリです。 https://github.com/torikatsupg/googleads_mobile_sdk_sample
ネイティブ広告以外の広告のサンプルもあります。もし何かの参考になれば幸いです。
実装
下準備
依存関係の追加
まずはパッケージの依存関係をpubspec.yamlに追加します。 pub.devのinstallingを参考に、適宜バージョンを読み替えてください。
pubspec.yaml
dependencies:
flutter:
sdk: flutter
+ google_mobile_ads: ^0.11.0+1
Admob IDの追加
次にAdmobのIDをAndroidManifest.xmlに追加する必要があります。
今回はサンプルの実装なので以下のIDを使用します。
ca-app-pub-3940256099942544~3347511713
適宜各自のIDに読み替えてください。
android/main/src/AndroidManifest.xml
<manifest>
<application>
.........
+ <meta-data
+ android:name="com.google.android.gms.ads.APPLICATION_ID"
+ android:value="ca-app-pub-3940256099942544~3347511713 "/>
<application>
<manifest>
SDKの初期化
最後にアプリ起動時にSDKの初期化をするようにします。 SDKの初期化は以下によって行います。
MobileAds.instance.initialize();
公式docによると初期化のタイミングはアプリ起動前がいいそうです。 今回は、run()で初期化します。
run.dart
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:googleads_mobile_sdk_sample/app.dart';
run() {
WidgetsFlutterBinding.ensureInitialized();
+ MobileAds.instance.initialize();
return runApp(
ProviderScope(
child: App(),
),
);
ネイティブ広告(Android)を実装する
ネイティブ広告の実装はざっくりとFlutter側の実装とネイティブ側の実装に別れます。
Flutter側の実装
ネイティブ広告は、Flutter側でウィジェットとして扱います。 なので、広告ウィジェットを作成する関数を定義し、UIに広告を組み込みます。
初めにlistenerを作成します。 とりあえず表示したいだけなら、広告の読み込みが完了したときのonAdLoadedと、onAdClosedでのリスナの開放ぐらいを実装しておけばいいと思います。
native_page.dart
Widget _buildNativeAd() {
final listener = AdListener(
onAdLoaded: (Ad ad) => ,
onAdFailedToLoad: (Ad ad, LoadAdError error) {
print('Ad failed to load: $error');
},
onAdOpened: (Ad ad) => print('Ad opened.'),
onAdClosed: (Ad ad) => print('Ad closed.'),
onApplicationExit: (Ad ad) => print('Left application.'),
onNativeAdClicked: (NativeAd ad) => print('Ad clicked.'),
onNativeAdImpression: (NativeAd ad) => print('Ad impression.'),
);
......
listenerの作成が終わったら、広告を作成します。 広告の作成には以下の4つを渡してあげる必要があります。
- 広告ユニットID 今回はサンプルとして用意された
ca-app-pub-3940256099942544/2247696110を使用します。 - このあとAndroid側で登録する任意のFactoryID(文字列)
AdRequestインスタンス- 先ほどつくったリスナ
実装は以下のようになります。
native_page.dart
......
final myNative = NativeAd(
adUnitId: 'ca-app-pub-3940256099942544/2247696110',
factoryId: 'adFactoryExample',
request: AdRequest(),
listener: listener,
);
myNative.load();
return AdWidget(ad: myNative);
広告の実装ができたら、広告の読み込みを開始しつつAdWidgetに広告を渡して、広告ウィジェットを作成します。
native_page.dart
......
myNative.load();
return AdWidget(ad: myNative);
}
Flutter側の実装は以上になります。
ネイティブ側での実装
初めに広告のUIを作成します。 Androidでは、UIをxml形式で記述してきます。 ここでandroid:id="...のように、Viewの要素にIDがいくつか指定されていることがわかります。 あとでこのIDをレイアウトにアクセスするときに使用します。
android/src/main/res/layout/my_native_ad.xml
<com.google.android.gms.ads.formats.UnifiedNativeAdView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</com.google.android.gms.ads.formats.UnifiedNativeAdView>
次にNativeAdFactoryを継承した、広告を作成するクラスを定義します。 今回はNativeAdFactoryExampleというクラス名にします。
android/src/main/kotlin/com/example.googleads_mobile_sdk_sample/NativeAdFactoryExample.kt
class NativeAdFactoryExample(private val layoutInflater: LayoutInflater) : NativeAdFactory {
override fun createNativeAd(nativeAd: UnifiedNativeAd?,
customOptions: MutableMap<String, Any>?): UnifiedNativeAdView {
val adView = layoutInflater.inflate(R.layout.my_native_ad, null)
as UnifiedNativeAdView
val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
val bodyView = adView.findViewById<TextView>(R.id.ad_body)
headlineView.text = nativeAd?.headline
bodyView.text = nativeAd?.body
adView.setBackgroundColor(Color.YELLOW)
adView.setNativeAd(nativeAd)
adView.headlineView = headlineView
adView.bodyView = bodyView
return adView
}
}
ここでやっていることは、レイアウトのxmlを読み込んできて、xmlに定義したID(android:id="...)を頼りに、各コンテンツを埋め込んで広告のUIを作成するといった感じです。
次に、Flutter側で定義したFactoryIDと、先ほど作成したFactoryクラスの紐付けを行います。
android/src/main/kotlin/com/example/googleads_mobile_sdk_sample/MainActivity.kt
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
flutterEngine.plugins.add(GoogleMobileAdsPlugin());
super.configureFlutterEngine(flutterEngine)
+ GoogleMobileAdsPlugin.registerNativeAdFactory(
+ flutterEngine,
+ "adFactoryExample",
+ NativeAdFactoryExample(layoutInflater)
+ )
}
```GoogleMobileAdsPlugin.registerNativeAdFactory```の引数に、Flutter側で定義した```adFactoryExample```というFactoryIDと、先ほど作成した```NativeAdFactoryExample```を渡しているのがわかります。
さらに、アプリ終了時に広告の削除処理を行うために```cleanUpFlutterEngine```を以下のようにオーバーライドします。
android/src/main/kotlin/com/example/googleads_mobile_sdk_sample/MainActivity.kt
……
override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
super.cleanUpFlutterEngine(flutterEngine)
GoogleMobileAdsPlugin.unregisterNativeAdFactory(
flutterEngine, "adFactoryExample"
)
}
これでネイティブ広告を表示できるようになりました!👏
## おわりに
今回はKotlinでネイティブ広告を実装する方法を紹介しました。
本当はIOS側の実装をswiftに読み替えて、一緒に紹介する予定でした。しかし、IOS開発やobjective-cに詳しくないために、ランタイムエラーを回避することができず断念しました。
サンプルをみていて気づいたことがありましたらissueをあげていただけると嬉しいです。
それでは良い開発ライフを!
-––