跳至主要内容

Android Integeration with AdMob MediationˍSDK8

詳細範例:

AdMob 20.5.0 Mediation Project (包含橫幅、插頁、原生廣告)。new-xxl.png

新增應用程式​

AdMob網站: https://apps.admob.com/

  • 進入 AdMob 網頁選擇 應用程式 > 新增應用程式

 500px

  • 選擇平台

  •  800px

  • 接著輸入應用程式名稱

  •  800px

  • 建立完成

  • 800px

    新增廣告單元​

    • 點選先前建立的應用程式並選擇 廣告單元 > 開始匯入

     800px

  • 選擇欲建立的廣告單元 (以橫幅廣告為例)

  •  800px

  • 輸入廣告單元名稱

  •  1000px

  • 建立完成,請記下 AdMob 的廣告單元ID

  • 800px

    新增中介服務群組​

    • 進入 AdMob 網頁選擇 中介服務 > 新增中介服務群組

     800px

  • 設定廣告格式、平台

  •  400px

  • 設定中介群組名稱並點選加入廣告單元

  •  1000px

  • 選擇先前建立的廣告單元 (以橫幅廣告為例)

  •  600px

  • 點選新增自訂事件,並設定下列相關資訊:

    有效千次曝光出價: 越高代表該家聯播網廣告曝光的機會越高

    Class Name: 根據您的專案輸入 mediation code 的 package name,如: com.taiwanmobile.pt.adp.mediation.TAMediaBanner (下方**實作 Mediation Code**章節會說明Mediation Code的實作方式)

    Parameter: 輸入您的 TAmedia 廣告版位ID

  •  1000px

     1000px

    TAmedia廣告版位ID​

     1000px

  • 點選完成後,中介服務群組的設置便結束

  • 1200px

    程式整合​

    1. 請參考**AdMob for Android** 網站提供的方式整合Google Ads SDK,此步驟會使用到**新增應用程式所取得的應用程式ID**

    2. 下載** TAMedia Android SDK,並參考 開始使用Getting Started** 整合TAMedia Android SDK

    2. 下載AdMob 20.5.0 Mediation Project,並整合下列Mediation Code進開發者專案中

    Mediation Code​

    依照下列方式實作AdMob所提供的CustomEventBanner

       package com.taiwanmobile.pt.adp.mediation
       
       import android.app.Activity
       import android.content.Context
       import android.os.Bundle
       import android.util.Log
       import com.google.android.gms.ads.AdRequest
       import com.google.android.gms.ads.AdSize
       import com.google.android.gms.ads.mediation.MediationAdRequest
       import com.google.android.gms.ads.mediation.customevent.CustomEventBanner
       import com.google.android.gms.ads.mediation.customevent.CustomEventBannerListener
       import com.taiwanmobile.pt.adp.view.*
     
     // 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaBanner註冊於中介服務群組, 如新增中介服務群組所述
       class TAMediaBanner : CustomEventBanner {
       
           private var adView: TWMAdView? = null
       
           override fun requestBannerAd(
               context: Context,
               customEventBannerListener: CustomEventBannerListener,
               serverParameter: String?,
               adSize: AdSize,
               mediationAdRequest: MediationAdRequest,
               bundle: Bundle?
           ) {
               // serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得
               Log.d(TAG, "requestBannerAd($serverParameter) invoked!!")
               adView = TWMAdView(context as Activity, convertAdSize(adSize), serverParameter)
               adView?.adListener = object : TWMAdViewListener {
                   override fun onReceiveAd(ad: TWMAd) {
                       customEventBannerListener.onAdLoaded(adView)
                   }
       
                   override fun onFailedToReceiveAd(ad: TWMAd, errorCode: TWMAdRequest.ErrorCode) {
                       customEventBannerListener.onAdFailedToLoad(
                           convertErrorCode(errorCode)
                       )
                   }
       
                   override fun onPresentScreen(ad: TWMAd) {
                       customEventBannerListener.onAdOpened()
                   }
       
                   override fun onDismissScreen(ad: TWMAd) {
                       customEventBannerListener.onAdClosed()
                   }
       
                   override fun onLeaveApplication(ad: TWMAd) {
                       customEventBannerListener.onAdClicked()
                       customEventBannerListener.onAdLeftApplication()
                   }
               }
               adView?.loadAd(TWMAdRequest())
           }
       
           override fun onDestroy() {
               adView?.destroy()
           }
       
           override fun onPause() {}
           override fun onResume() {}
       
           //將AdMob的AdSize轉換為TWMAdSize
           private fun convertAdSize(adSize: AdSize): TWMAdSize {
               return when {
                   isAdSizeEqual(adSize, TWMAdSize.BANNER) -> {
                       TWMAdSize.BANNER
                   }
                   isAdSizeEqual(adSize, TWMAdSize.BANNER_1200X627) -> {
                       TWMAdSize.BANNER_1200X627
                   }
                   isAdSizeEqual(adSize, TWMAdSize.BANNER_300X250) -> {
                       TWMAdSize.BANNER_300X250
                   }
                   isAdSizeEqual(adSize, TWMAdSize.SMART_BANNER) -> {
                       TWMAdSize.SMART_BANNER
                   }
                   else -> {
                       TWMAdSize.BANNER
                   }
               }
           }
       
           private fun isAdSizeEqual(adSize: AdSize, twmAdSize: TWMAdSize): Boolean {
               return (adSize.width == twmAdSize.width
                       && adSize.height == twmAdSize.height)
           }
       
           //將TAMedia ErrorCode轉換為AdMob的ErrorCode
           private fun convertErrorCode(errorCode: TWMAdRequest.ErrorCode): Int {
               return when (errorCode) {
                   TWMAdRequest.ErrorCode.INTERNAL_ERROR -> {
                       AdRequest.ERROR_CODE_INTERNAL_ERROR
                   }
                   TWMAdRequest.ErrorCode.INVALID_REQUEST -> {
                       AdRequest.ERROR_CODE_INVALID_REQUEST
                   }
                   TWMAdRequest.ErrorCode.NETWORK_ERROR -> {
                       AdRequest.ERROR_CODE_NETWORK_ERROR
                   }
                   TWMAdRequest.ErrorCode.NO_FILL -> {
                       AdRequest.ERROR_CODE_NO_FILL
                   }
                   else -> AdRequest.ERROR_CODE_NETWORK_ERROR
               }
           }
       
           companion object {
               private const val TAG = "TAMediaBanner"
           }
       }

    Interstitial​

    依照下列方式實作AdMob所提供的CustomEventInterstitial

       package com.taiwanmobile.pt.adp.mediation
       
       import android.app.Activity
       import android.content.Context
       import android.os.Bundle
       import android.util.Log
       import com.google.android.gms.ads.AdRequest
       import com.google.android.gms.ads.mediation.MediationAdRequest
       import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitial
       import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitialListener
       import com.taiwanmobile.pt.adp.view.TWMAd
       import com.taiwanmobile.pt.adp.view.TWMAdRequest
       import com.taiwanmobile.pt.adp.view.TWMAdViewListener
       import com.taiwanmobile.pt.adp.view.TWMInterstitialAd
     
     // 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaInterstitial註冊於中介服務群組, 如新增中介服務群組所述
       class TAMediaInterstitial : CustomEventInterstitial {
       
           private var interstitialAd: TWMInterstitialAd? = null
       
           override fun requestInterstitialAd(
               context: Context,
               customEventInterstitialListener: CustomEventInterstitialListener,
               serverParameter: String?,
               mediationAdRequest: MediationAdRequest,
               bundle: Bundle?
           ) {
               // serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得
               Log.d(TAG, "requestInterstitialAd($serverParameter) ")
               interstitialAd = TWMInterstitialAd(context as Activity, serverParameter as String)
               interstitialAd?.setAdListener(object : TWMAdViewListener {
       
                   override fun onReceiveAd(ad: TWMAd) {
                       customEventInterstitialListener.onAdLoaded()
                   }
       
                   override fun onFailedToReceiveAd(ad: TWMAd, errorCode: TWMAdRequest.ErrorCode) {
                       customEventInterstitialListener.onAdFailedToLoad(
                           convertErrorCode(errorCode)
                       )
                   }
       
                   override fun onPresentScreen(ad: TWMAd) {
                       customEventInterstitialListener.onAdOpened()
                   }
       
                   override fun onDismissScreen(ad: TWMAd) {
                       customEventInterstitialListener.onAdClosed()
                   }
       
                   override fun onLeaveApplication(ad: TWMAd) {
                       customEventInterstitialListener.onAdClicked()
                       customEventInterstitialListener.onAdLeftApplication()
                   }
               })
               interstitialAd?.loadAd(TWMAdRequest())
           }
       
           override fun showInterstitial() {
               interstitialAd?.show()
           }
       
           override fun onDestroy() {}
           override fun onPause() {}
           override fun onResume() {}
       
           // 將TAMedia ErrorCode轉換為AdMob的ErrorCode
           private fun convertErrorCode(errorCode: TWMAdRequest.ErrorCode): Int {
               return when (errorCode) {
                   TWMAdRequest.ErrorCode.INTERNAL_ERROR -> {
                       AdRequest.ERROR_CODE_INTERNAL_ERROR
                   }
                   TWMAdRequest.ErrorCode.INVALID_REQUEST -> {
                       AdRequest.ERROR_CODE_INVALID_REQUEST
                   }
                   TWMAdRequest.ErrorCode.NETWORK_ERROR -> {
                       AdRequest.ERROR_CODE_NETWORK_ERROR
                   }
                   TWMAdRequest.ErrorCode.NO_FILL -> {
                       AdRequest.ERROR_CODE_NO_FILL
                   }
                   else -> AdRequest.ERROR_CODE_NETWORK_ERROR
               }
           }
       
           companion object {
               private const val TAG = "TAMediaInterstitial"
           }
       }

    Native​

    依照下列方式實作AdMob所提供的CustomEventNative

    從AdMob廣告設定serverParameter得知TAmedia原生廣告版位, 進而對TAmedia SDK請求原生廣告, 詳情可參考 TAmedia廣告版位ID

    下列為附加功能(Optional), 預設關閉, 如需使用再將屬性設為true, 詳情可參考 TWMNativeAdOptions

    videoStartUnmuted: 影片預設開啟聲音

    disableImageLoading: 取消圖片下載, 加速廣告請求

    videoCustomControlRequest: 取消影片內控制項

    mediaPreferImage: TWMMediaView改呈現圖片

    package com.taiwanmobile.pt.adp.mediation

    import android.content.Context
    import android.os.Bundle
    import com.google.android.gms.ads.mediation.NativeMediationAdRequest
    import com.google.android.gms.ads.mediation.customevent.CustomEventNative
    import com.google.android.gms.ads.mediation.customevent.CustomEventNativeListener
    import com.taiwanmobile.pt.adp.mediation.native.TANativeEventForwarder
    import com.taiwanmobile.pt.adp.nativead.TWMNativeAdOptions
    import com.taiwanmobile.pt.adp.view.TWMAdRequest
    import com.taiwanmobile.pt.adp.view.TWMNativeAd

    // 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAmediaNative註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述
    class TAmediaNative : CustomEventNative {

    private var twmNativeAd: TWMNativeAd? = null
    // optional. Set true when the feature below is needed.
    // http://wiki.tamedia.com.tw/androidDoc/library/com.taiwanmobile.pt.adp.nativead/-t-w-m-native-ad-options/index.html
    private val videoStartUnmuted = false
    private val disableImageLoading = false
    private val videoCustomControlRequest = false
    private val mediaPreferImage = false

    override fun onDestroy() {
    twmNativeAd?.destroy()
    }

    override fun onPause() {}

    override fun onResume() {}

    override fun requestNativeAd(
    context: Context,
    customEventNativeListener: CustomEventNativeListener,
    serverParameter: String?,
    nativeMediationAdRequest: NativeMediationAdRequest,
    extra: Bundle?
    ) {
    serverParameter?.let { twmAdUnitId ->
    twmNativeAd = TWMNativeAd(context, twmAdUnitId).also { nativeAd ->
    nativeAd.setAdListener(
    TANativeEventForwarder(
    customEventNativeListener,
    nativeMediationAdRequest.nativeAdRequestOptions
    )
    )
    }.apply {
    val request = TWMAdRequest().apply {
    val nativeAdOptions = mutableListOf<TWMNativeAdOptions>()
    if (videoStartUnmuted) {
    nativeAdOptions.add(TWMNativeAdOptions.VIDEO_START_UNMUTED)
    }
    if (disableImageLoading) {
    nativeAdOptions.add(TWMNativeAdOptions.DISABLE_IMAGE_LOADING)
    }
    if (videoCustomControlRequest) {
    nativeAdOptions.add(TWMNativeAdOptions.VIDEO_CUSTOM_CONTROLS_REQUESTED)
    }
    if (mediaPreferImage) {
    nativeAdOptions.add(TWMNativeAdOptions.MEDIA_PREFER_IMAGE)
    }
    if (nativeAdOptions.size > 0) {
    setNativeAdOptions(nativeAdOptions.toTypedArray())
    }
    }
    loadAd(request)
    }
    }
    }

    }

    依照下列方式實作CustomEventNative需用到的TANativeEventForwarder

    package com.taiwanmobile.pt.adp.mediation.native

    import com.google.android.gms.ads.AdRequest
    import com.google.android.gms.ads.mediation.customevent.CustomEventNativeListener
    import com.google.android.gms.ads.nativead.NativeAdOptions
    import com.taiwanmobile.pt.adp.view.TWMAd
    import com.taiwanmobile.pt.adp.view.TWMAdRequest
    import com.taiwanmobile.pt.adp.view.TWMAdViewListener
    import com.taiwanmobile.pt.adp.view.TWMNativeAd

    @Suppress("DEPRECATION")
    class TANativeEventForwarder(private val listener: CustomEventNativeListener,
    private val options: NativeAdOptions
    ) : TWMAdViewListener {
    override fun onDismissScreen(ad: TWMAd) {}

    override fun onFailedToReceiveAd(ad: TWMAd, errorCode: TWMAdRequest.ErrorCode) {
    listener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL)
    }

    override fun onLeaveApplication(ad: TWMAd) {
    listener.onAdClicked()
    listener.onAdLeftApplication()
    }

    override fun onPresentScreen(ad: TWMAd) {
    listener.onAdImpression()
    }

    override fun onReceiveAd(ad: TWMAd) {
    when (ad is TWMNativeAd) {
    true -> {
    val mapper = TANativeAdMapper(ad)
    listener.onAdLoaded(mapper)
    }
    false -> {
    listener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL)
    }
    }
    }

    }

    依照下列方式實作TANativeEventForwarder需用到的TANativeAdMapper

    package com.taiwanmobile.pt.adp.mediation.native

    import android.view.View
    import android.widget.FrameLayout
    import com.google.android.gms.ads.mediation.UnifiedNativeAdMapper
    import com.google.android.gms.ads.nativead.NativeAdAssetNames
    import com.taiwanmobile.pt.adp.nativead.TWMMediaView
    import com.taiwanmobile.pt.adp.view.TWMNativeAd
    import com.taiwanmobile.pt.adp.view.TWMNativeAdView
    import com.taiwanmobile.pt.guide.R

    class TANativeAdMapper(private val nativeAd: TWMNativeAd) : UnifiedNativeAdMapper() {

    init {
    overrideClickHandling = true
    overrideImpressionRecording = true

    // Mapping TWMNativeAd to AdMob Native AD resource
    // headline
    nativeAd.nativeAdContent.longSubject?.let { headline = it }
    // body
    nativeAd.nativeAdContent.body?.let { body = it }
    // call to action
    nativeAd.nativeAdContent.callToAction?.let { callToAction = it }
    // icon
    nativeAd.nativeAdContent.iconSquare?.let { image ->
    image.getDrawable()?.let { drawable ->
    image.getUri()?.let { uri ->
    icon = TANativeMappedImage(drawable, uri)
    }
    }
    }
    // mediaView
    nativeAd.nativeAdContent.mediaContent?.let {
    setHasVideoContent(true)
    }
    }

    override fun trackViews(
    containerView: View,
    clickableAssetViews: MutableMap<String, View>,
    nonClickableAssetViews: MutableMap<String, View>
    ) {
    super.trackViews(containerView, clickableAssetViews, nonClickableAssetViews)

    // TWMNativeAdView population
    containerView.findViewById<TWMNativeAdView>(R.id.taNativeAdView)?.apply {
    // headline
    clickableAssetViews[NativeAdAssetNames.ASSET_HEADLINE]?.let { headlineView ->
    setLongSubjectView(headlineView)
    }
    // body
    clickableAssetViews[NativeAdAssetNames.ASSET_BODY]?.let { bodyView ->
    setBodyView(bodyView)
    }
    // call to action
    clickableAssetViews[NativeAdAssetNames.ASSET_CALL_TO_ACTION]?.let { ctaView ->
    setCallToActionView(ctaView)
    }
    // icon
    clickableAssetViews[NativeAdAssetNames.ASSET_ICON]?.let { iconView ->
    setSquareIconView(iconView)
    }
    // mediaView
    if (hasVideoContent()) {
    clickableAssetViews[NativeAdAssetNames.ASSET_MEDIA_VIDEO]?.let { mediaView ->
    nativeAd.nativeAdContent.mediaContent?.let { mediaContent ->
    val taMediaView = TWMMediaView(mediaView.context).apply {
    setMediaContent(mediaContent)
    layoutParams = mediaView.layoutParams
    }
    // append TWMMediaView on AdMob MediaView
    (mediaView as FrameLayout?)?.addView(taMediaView)
    // specify TWMMediaView in TWMNativeAdView
    setMediaView(taMediaView)
    // (optional) cta text size
    taMediaView.setCTATextSize(12.0f)
    // (optional) video count down text size
    taMediaView.setVideoCountdownTextSize(14.0f)
    // (optional) volume image size
    taMediaView.setVolumeImageSize(20)
    }
    }
    } else {
    clickableAssetViews[NativeAdAssetNames.ASSET_MEDIA_VIDEO]?.let { mediaView ->
    mediaView.visibility = View.GONE
    }
    }
    // final step of population, specify TWMNativeAd object to TWMNativeView
    setNativeAd(nativeAd)
    }

    }
    }

    依照下列方式實作TANativeAdMapper需用到的TANativeMappedImage

    @file:Suppress("DEPRECATION")

    package com.taiwanmobile.pt.adp.mediation.native

    import android.graphics.drawable.Drawable
    import android.net.Uri
    import com.google.android.gms.ads.formats.NativeAd

    /**
    * A Image class that fits the the [NativeAd.Image] abstract class and can be filled with
    * assets returned by TAmedia SDK.
    */
    class TANativeMappedImage(
    private val drawable: Drawable,
    private val uri: Uri
    ) :
    NativeAd.Image() {
    override fun getDrawable(): Drawable = drawable
    override fun getUri(): Uri = uri
    override fun getScale(): Double = 1.0
    }

    Developer Sample Code​

    以下以Banner為例:

    1. 在MainActivity.kt中輸入AdUnit Id

       companion object {
           private const val ADUNIT_ID_BANNER_320x50 = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_BANNER_300x250 = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_SMART_BANNER = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_INTERSTITIAL = "{AdMob Interstitial AdUnit Id}"
           private const val ADUNIT_ID_NATIVE = "{AdMob Native AdUnit Id}"
           const val KEY_ADUNITID = "adUnitId"
           const val KEY_ADSIZE = "adSize"
       }

    2. 在layout檔案中加入可放置廣告的RelativeLayout(※僅供參考,開發者可依照自訂的layout進行配置使用)

       <RelativeLayout
           android:id="@+id/adContainer"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_centerHorizontal="true"
           android:layout_alignParentBottom="true">
       </RelativeLayout>

    3. BannerActivity 程式加入Banner的宣告, 設定AdUnitId與AdSize

       class BannerActivity : AppCompatActivity() {
           private var adView: AdView? = null
           override fun onCreate(savedInstanceState: Bundle?) {
               super.onCreate(savedInstanceState)
               setContentView(R.layout.activity_banner)
               val adContainer = findViewById<View>(R.id.adContainer) as RelativeLayout
               val args = intent.extras
               if (args != null) {
                   val adUnitId = args.getString(MainActivity.KEY_ADUNITID)
                   val adSize: AdSize = when (args.getString(MainActivity.KEY_ADSIZE)) {
                       BANNER_320x50 -> {
                           AdSize.BANNER
                       }
                       BANNER_300x250 -> {
                           AdSize.MEDIUM_RECTANGLE
                       }
                       else -> {
                           val displayMetrics = resources.displayMetrics
                           val dpWidth = (displayMetrics.widthPixels / displayMetrics.density).toInt()
                           AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(
                               this,
                               dpWidth
                           )
                       }
                   } 
                    // Banner initial
                   adUnitId?.let {
                       val request = AdRequest.Builder().build()
                       adView = AdView(this@BannerActivity)
                       adView?.adUnitId = it
                       adView?.adSize = adSize
                       adView?.adListener = AdListenerImpl()
                       adView?.loadAd(request)
                       // add view into layout
                       adContainer.addView(adView)
                   }
               }
           }
    }

    Interstitial​

    === Native ===

    以下以Native為例:

    1. 在MainActivity.kt中輸入AdUnit Id

       companion object {
           private const val ADUNIT_ID_BANNER_320x50 = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_BANNER_300x250 = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_SMART_BANNER = "{AdMob Banner AdUnit Id}"
           private const val ADUNIT_ID_INTERSTITIAL = "{AdMob Interstitial AdUnit Id}"
           private const val ADUNIT_ID_NATIVE = "{AdMob Native AdUnit Id}"
           const val KEY_ADUNITID = "adUnitId"
           const val KEY_ADSIZE = "adSize"
       }

    2. NativeActivity的layout如下, 在layout檔案中加入可放置原生廣告的nativeContainer(※這裡以FrameLayout為例,開發者可依照自訂的layout進行配置使用)

       <LinearLayout
           xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:paddingBottom="@dimen/activity_vertical_margin"
           android:paddingLeft="@dimen/activity_horizontal_margin"
           android:paddingRight="@dimen/activity_horizontal_margin"
           android:paddingTop="@dimen/activity_vertical_margin"
           android:orientation="vertical">
       <FrameLayout
               android:id="@+id/native_container"
               android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:layout_marginTop="@dimen/activity_vertical_margin" />
       </LinearLayout>

    3. 準備廣告佈局native_ad.xml, 在com.google.android.gms.ads.nativead.NativeAdView上添加TWMNativeAdView

       <com.google.android.gms.ads.nativead.NativeAdView
           xmlns:android="http://schemas.android.com/apk/res/android"
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:orientation="vertical">
           <com.taiwanmobile.pt.adp.view.TWMNativeAdView
               android:id="@+id/taNativeAdView"
               android:layout_width="match_parent"
               android:layout_height="wrap_content">
               <LinearLayout
                   android:layout_width="match_parent"
                   android:layout_height="wrap_content"
                   android:layout_gravity="center"
                   android:background="#FFFFFF"
                   android:minHeight="50dp"
                   android:orientation="vertical">
                   <LinearLayout
                       android:layout_width="match_parent"
                       android:layout_height="wrap_content"
                       android:orientation="vertical"
                       android:paddingLeft="20dp"
                       android:paddingTop="3dp"
                       android:paddingRight="20dp">
                       <LinearLayout
                           android:layout_width="match_parent"
                           android:layout_height="wrap_content"
                           android:orientation="horizontal">
                           <ImageView
                               android:id="@+id/ad_app_icon"
                               android:layout_width="40dp"
                               android:layout_height="40dp"
                               android:adjustViewBounds="true"
                               android:paddingEnd="5dp"
                               android:paddingRight="5dp"
                               android:paddingBottom="5dp" />
                           <LinearLayout
                               android:layout_width="match_parent"
                               android:layout_height="wrap_content"
                               android:orientation="vertical">
                               <TextView
                                   android:id="@+id/ad_headline"
                                   android:layout_width="match_parent"
                                   android:layout_height="wrap_content"
                                   android:textColor="#0000FF"
                                   android:textSize="16sp"
                                   android:textStyle="bold" />
                           </LinearLayout>
                       </LinearLayout>
                       <LinearLayout
                           android:layout_width="match_parent"
                           android:layout_height="wrap_content"
                           android:orientation="vertical">
                       <TextView
                           android:id="@+id/ad_body"
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:layout_marginEnd="20dp"
                           android:layout_marginRight="20dp"
                           android:textSize="12sp" />
                       <com.google.android.gms.ads.nativead.MediaView
                           android:id="@+id/ad_media"
                           android:layout_width="250dp"
                           android:layout_height="175dp"
                           android:layout_gravity="center_horizontal"
                           android:layout_marginTop="5dp" />
                       <LinearLayout
                           android:layout_width="wrap_content"
                           android:layout_height="wrap_content"
                           android:layout_gravity="end"
                           android:orientation="horizontal"
                           android:paddingTop="10dp"
                               android:paddingBottom="10dp">
                               <Button
                                   android:id="@+id/ad_call_to_action"
                                   android:layout_width="wrap_content"
                                   android:layout_height="wrap_content"
                                   android:gravity="center"
                                   android:textSize="12sp" />
                           </LinearLayout>
                       </LinearLayout>
                   </LinearLayout>
               </LinearLayout>
           </com.taiwanmobile.pt.adp.view.TWMNativeAdView>
       </com.google.android.gms.ads.nativead.NativeAdView>

    4. 使用AdMob AdLoader載入原生廣告

    當AdLoader取得原生廣告時, 產出(inflate)原生廣告佈局native_ad.xml並進行NativeAdView物件填充(population), 詳情可參考下方populateNativeAdView()

    NativeAdView填充下列屬性: headline, body, call to action, icon, mediaView等資訊

    填充後將native_ad.xml物件加入nativeContainer

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityNativeBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)

    val args = intent.extras
    args?.let {
    val adUnitId = args.getString(MainActivity.KEY_ADUNITID) ?: ""
    val adLoader = AdLoader.Builder(this, adUnitId)
    .forNativeAd { ad: NativeAd ->
    nativeAd = ad
    val adLayout = NativeAdBinding.inflate(layoutInflater)
    populateNativeAdView(ad, adLayout)
    binding.nativeContainer.removeAllViews()
    binding.nativeContainer.addView(adLayout.root)

    // If this callback occurs after the activity is destroyed, you
    // must call destroy and return or you may get a memory leak.
    // Note `isDestroyed` is a method on Activity.

    if (isDestroyed) {
    ad.destroy()
    return@forNativeAd
    }
    }
    .withAdListener(object : AdListener() {
    override fun onAdFailedToLoad(adError: LoadAdError) {
    Toast.makeText(this@NativeActivity, "onAdFailedToLoad", Toast.LENGTH_LONG)
    .show()
    }

    override fun onAdClicked() {
    super.onAdClicked()
    Toast.makeText(this@NativeActivity, "onAdClicked", Toast.LENGTH_LONG)
    .show()
    }

    override fun onAdImpression() {
    super.onAdImpression()
    Toast.makeText(this@NativeActivity, "onAdImpression", Toast.LENGTH_LONG)
    .show()
    }
    })
    .withNativeAdOptions(
    NativeAdOptions.Builder()
    // Methods in the NativeAdOptions.Builder class can be
    // used here to specify individual options settings.
    .build()
    )
    .build()
    adLoader.loadAd(AdRequest.Builder().build())
    }
    }

    /**
    * Populates a [NativeAdView] object with data from a given [NativeAd].
    *
    * @param nativeAd the object containing the ad's assets
    * @param viewBinding the view binding object [NativeAdBinding] contains the [NativeAdView]
    */
    private fun populateNativeAdView(nativeAd: NativeAd, viewBinding: NativeAdBinding) {

    // fetch NativeAdView from NativeAdBinding
    val nativeAdView: NativeAdView = viewBinding.root

    // headline
    if (nativeAd.headline == null) {
    viewBinding.adHeadline.visibility = View.INVISIBLE
    } else {
    viewBinding.adHeadline.visibility = View.VISIBLE
    viewBinding.adHeadline.text = nativeAd.headline
    nativeAdView.headlineView = viewBinding.adHeadline
    }
    // body
    if (nativeAd.body == null) {
    viewBinding.adBody.visibility = View.INVISIBLE
    } else {
    viewBinding.adBody.visibility = View.VISIBLE
    viewBinding.adBody.text = nativeAd.body
    nativeAdView.bodyView = viewBinding.adBody
    }
    // call to action
    if (nativeAd.callToAction == null) {
    viewBinding.adCallToAction.visibility = View.INVISIBLE
    } else {
    viewBinding.adCallToAction.visibility = View.VISIBLE
    viewBinding.adCallToAction.text = nativeAd.callToAction
    nativeAdView.callToActionView = viewBinding.adCallToAction
    }
    // icon
    if (nativeAd.icon == null) {
    viewBinding.adAppIcon.visibility = View.GONE
    } else {
    nativeAd.icon?.drawable?.let {
    viewBinding.adAppIcon.setImageDrawable(it)
    viewBinding.adAppIcon.visibility = View.VISIBLE
    nativeAdView.iconView = viewBinding.adAppIcon
    }
    }
    // mediaView
    nativeAdView.mediaView = viewBinding.adMedia
    nativeAdView.setNativeAd(nativeAd)
    }

    回首頁