Flutterのネイティブ広告をKotlinで実装する
はじめに
先日、Google Mobile Adsのflutterプラグインが発表されました。 developers.google.cn
先祖のプラグインにあたる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"
)
}
これでネイティブ広告を表示できるようになりました!👏 [f:id:torikatsu923:20210413010107p:plain] ## おわりに 今回はKotlinでネイティブ広告を実装する方法を紹介しました。 本当はIOS側の実装をswiftに読み替えて、一緒に紹介する予定でした。しかし、IOS開発やobjective-cに詳しくないために、ランタイムエラーを回避することができず断念しました。 サンプルをみていて気づいたことがありましたらissueをあげていただけると嬉しいです。 それでは良い開発ライフを!