TAMedia Wiki

Android Integeration with AdMob MediationˍSDK8

詳細範例:

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

新增應用程式

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

 500px


  • 選擇平台

  •  800px


  • 接著輸入應用程式名稱

  •  800px


  • 建立完成

  • 800px




    新增廣告單元

     800px


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

  •  800px


  • 輸入廣告單元名稱

  •  1000px


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

  • 800px




    新增中介服務群組

     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)
    
        }



    回首頁