課題
AndroidでAdMobバナー広告はアダプティブ バナー使用します。
よくある広告バナーをアプリ上部or下部に常時表示するアプリでは、リンク先の通り以下のように実装します。(レイアウトの呼び出しはDataBindingを使用しています。)
MainActivity
class MainActivity : AppCompatActivity(R.layout.activity_main) {
...
private lateinit var adView: AdView
private val adSize: AdSize
get() {
val display = windowManager.defaultDisplay
val outMetrics = DisplayMetrics()
display.getMetrics(outMetrics)
val density = outMetrics.density
var adWidthPixels = binding.adViewContainer.width.toFloat()
if (adWidthPixels == 0f) {
adWidthPixels = outMetrics.widthPixels.toFloat()
}
val adWidth = (adWidthPixels / density).toInt()
return AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(this, adWidth)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
setupAdMob()
...
}
private fun setupAdMob() {
MobileAds.initialize(this)
adView = AdView(this)
binding.adViewContainer.addView(adView)
loadBanner()
}
private fun loadBanner() {
adView.adUnitId = getString(R.string.banner_ad_unit_id)
adView.adSize = adSize
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)
}
}
activity_main.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<!-- ヘッダー固定広告のためのコンテナ -->
<FrameLayout
android:id="@+id/ad_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<!-- コンテンツ領域 -->
<fragment
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
/>
</LinearLayout>
</layout>
レイアウトの構築と広告ロードでは広告ロードの方が遅いため、広告ロードされるまでadViewContainer
はサイズ0で表示されず、ロード完了時に表示領域が現れることになります。これでは突然広告が表示され不快な表示になったり、コンテンツ領域のサイズが変わるため混乱をきたします。
解決: プレースホルダーの表示
広告がロードされるまでの間プレースホルダーを表示して違和感のないレイアウトにします。
loadBanner
関数にプレースホルダー表示を追加します。
MainActivity
class MainActivity : AppCompatActivity(R.layout.activity_main) {
...
private fun loadBanner() {
adView.adUnitId = getString(R.string.banner_ad_unit_id)
adView.adSize = adSize
val adRequest = AdRequest.Builder().build()
adView.loadAd(adRequest)
// プレースホルダー用のViewをadViewContainerに追加
val placeholderView = adPlaceHolderView(this, adView.adSize)
binding.adViewContainer.addView(placeholderView)
// 広告ロード完了時にプレースホルダーを除去
adView.adListener = object : AdListener() {
override fun onAdLoaded() {
binding.adViewContainer.removeView(placeholderView)
adView.adListener = null
}
}
}
}
fun adPlaceHolderView(context: Context, adSize: AdSize): View {
return View(context).apply {
val widthInPixels = adSize.getWidthInPixels(context)
val heightInPixels = adSize.getHeightInPixels(context)
layoutParams = ViewGroup.LayoutParams(widthInPixels, heightInPixels)
setBackgroundColor(ContextCompat.getColor(context, R.color.grey400))
}
}
表示する広告サイズが事前に分かっていれば静的にサイズをしても良いですが、アダプティブバナー(前身のスマートバナーも)アプリの表示サイズに応じて動的に広告サイズが変わります。したがって、AdSize
からこれから表示される広告サイズを取得することで、適切なサイズのプレースホルダーを表示できます。