flutterでAdMobのバナーを表示してみるテスト。 emulatorのOSイメージの設定でバナーが表示されない問題にハマった。参考記事もあまり見当たらなかった。私だけか。。? とりあえず実装の流れ。
ライブラリ
flutter上でadmobを実装するためのライブラリは数種類あるが、公式から新しいのでたらしいのでgoogle_mobile_adsを使う。 Google Mobile Ads for Flutter
インストール
flutter pub get google_mobile_ads
設定
Mobile Ads SDK(Android)
公式を参考に
app/build.gradle
, AndroidManifest.xml
に追記
これだけだとエラー出てくると思う。 google_mobile_adsを使うにはkotlinとかsdkのバージョンを上げろ的なことを言われる。
android {
compileSdkVersion 31 // 変更
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.testtest"
minSdkVersion 19 // 変更
targetSdkVersion 30 // 変更
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.android.gms:play-services-ads:20.6.0' // 追加
}
デフォだとflutter.gradleから値を持って来られるが直書きでオーバーライドしてしまうと flutter runが通るようになる。
実装
こんな感じでBLOC実装。デバッグの時はdebug用のIDを読めるような仕組みにする。
abstract class AdDictAbs {
String get banner;
}
// android
class adDictAndroid implements AdDictAbs {
final String banner = 'ca-app-pub-xxxxxxxxx/yyyyyyyyyy';
}
class adDictAndroidDebug implements AdDictAbs {
final String banner = 'ca-app-pub-3940256099942544/6300978111';
}
// ios
class adDictiOS implements AdDictAbs {
final String banner = '#';
}
class adDictiOSDebug implements AdDictAbs {
final String banner = 'ca-app-pub-3940256099942544/2934735716';
}
class AdState {
Future<InitializationStatus> initialization;
AdState(this.initialization);
// String get bannerAdUnitId => Platform.isAndroid
}
bool debugMode = true;
class AdDict {
static AdDictAbs Android =
(debugMode) ? adDictAndroidDebug() : adDictAndroid();
static AdDictAbs iOS = (debugMode) ? adDictiOSDebug() : adDictiOS();
}
class AdBloc {
final _bannerSubject = BehaviorSubject<BannerAd?>();
Stream<BannerAd?> get bannerStream => _bannerSubject.stream;
void bannerInit() {
AdRequest _request = const AdRequest();
print('banner init !!! bannerid ${AdDict.Android.banner}');
BannerAd(
size: AdSize.banner,
adUnitId: AdDict.Android.banner,
listener: BannerAdListener(
onAdLoaded: (ad) {
print("onADLOADEDD !!!!! bannerad $ad");
_bannerSubject.sink.add(ad as BannerAd);
},
onAdFailedToLoad: (Ad ad, LoadAdError error) {
print('$BannerAd failedToLoad!!!!!: $error');
_bannerSubject.value?.dispose();
},
onAdOpened: (Ad ad) => print('$BannerAd onAdOpened'),
onAdClosed: (Ad ad) => print('$BannerAd onAdClosed'),
),
request: _request)
.load();
}
void dispose() {
_bannerSubject.value?.dispose();
_bannerSubject.close();
}
}
widget部分はこんな。
class MainPage extends StatelessWidget {
const MainPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
final adbloc = Provider.of<AdBloc>(context);
void testinit() async {
await Future.delayed(const Duration(milliseconds: 100));
adbloc.bannerInit();
}
testinit();
return Scaffold(
backgroundColor: tabBg,
body: Container(
child: Text('Main Body Area Hello')
),
bottomNavigationBar: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('bottom banner'),
StreamBuilder<BannerAd?>(
stream: adbloc.bannerStream,
builder: (context, snapshot) {
BannerAd? ad = snapshot.data;
print('adad $ad');
if (ad == null) return Container();
return SizedBox(
width: ad.size.width.toDouble(),
height: ad.size.height.toDouble(),
child: AdWidget(ad: ad),
);
},
)
],
),
),
);
}
}
エラー
表示できるかと思いきやエラー。
W/GooglePlayServicesUtil(28945): com.example.testtest requires the Google Play Store, but it is missing.
I/Ads (28945): Ad failed to load : 0
I/flutter (28945): BannerAd failedToLoad!!!!!: LoadAdError(code: 0, domain: com.google.android.gms.ads, message: Internal error., responseInfo: ResponseInfo(responseId: null, mediationAdapterClassName: , adapterResponses: []))
google play storeに登録しないと表示できない雰囲気か?と思いつつ
ここをチェック 広告が表示されない場合の一般的な理由 しかし良い回答がない。
どうやらemulatorだと確認できない?
実機で確認してみたところ
W/Ads ( 9399): Not retrying to fetch app settings
I/Ads ( 9399): Ad failed to load : 3
I/flutter ( 9399): BannerAd failedToLoad!!!!!: LoadAdError(code: 3, domain: com.google.android.gms.ads, message: Publisher data not found. <https://support.google.com/admob/answer/9905175#9>, responseInfo: ResponseInfo(responseId: null, mediationAdapterClassName: , adapterResponses: []))
publisher data not found.
パブリッシャー データが見つかりません 意味: この広告ユニットのパブリッシャーのデータが見つかりません。広告ユニットを追加して間もない場合は、広告が表示されるまでに時間がかかることがあります。
対応策: 新しい広告ユニットが表示されるまで 1 時間ほどお待ちください。広告ユニットを追加してから 1 時間を超えている場合は次の対応を行います。
広告ユニットコードが正しいことを確認する お支払い情報に未入力の箇所がないか、その他に設定上の問題がないかなど、アカウントのエラーを確認する ポリシー センターでポリシーに関する問題を解決する 注: 無効な操作が原因でアカウントが無効になっている場合、そのアカウントにログインすることはできません。詳細
-> 未設定の本番用IDを指定していまっていたのでtest用IDを使用するように変更
無事実機では表示されました。
emulatorで表示するには?
再度さきほどのエラーログを見返してみて、そのままの意味で受け止める。google play storeがないのが表示できていない理由?
W/GooglePlayServicesUtil(28945): com.example.testtest requires the Google Play Store, but it is missing.
そして私はemulatorにPixel 4aを使っていたがどうやらPixel4aのOSイメージにはgoogle play storeが入っていないらしい。Nexusだとあるらしい。 そして他にもgoogle関連のserviceで必要なのがあるぽいのでSDKManagerでインストールする。
インストール後にADKManagerからemulatorを作成する。 これをgoogle play storeに マークがついてる。
これでok runしてみると、
はい。無事表示されました。 ひっかけだった。
ちなみにemulatorがデフォだとwifi接続できてなかったのでこちらのサイトを参考にして設定した。