TAMedia Wiki

Android Integeration with Ad Manager Mediation

詳細範例

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


新增廣告單元 / 收益群組

登入Google Ad Manager

https://admanager.google.com/home/
 center | 800px

橫幅(Banner)

center | 600px
  • 名稱: GAM_Mediation_Android_Banner_320x50

  • 大小: 320x50

  • center | 800px
  • 新增收益群組

  • center | 800px
  • 名稱: GAM_Mediation_Android_Banner_320x50

  • 狀態: 有效

  • 廣告格式: 橫幅

  • center | 1000px
  • 新增收益夥伴

  •  center | 1000px

  • 其他收益夥伴詳細資訊

  •  center | 600px

  • Label: 用於AdManagerAdView.adUnitId

  • Class Name: com.taiwanmobile.pt.gam.mediation.TAmediaGAMCustomEvent

  • Parameter: TAmedia廣告版位



  • 插頁(Interstitial)

    center | 600px
  • 名稱: GAM_Mediation_Android_Interstitial

  • 大小: 1024x768, 768x1024, 480x320, 320x480

  • center | 1000px
  • 新增收益群組

  • center | 1000px
  • 名稱: GAM_Mediation_Android_Interstitial

  • 狀態: 有效

  • 廣告格式: 插頁式

  • center | 1000px
  • 新增收益夥伴

  •  center | 1000px

  • 其他收益夥伴詳細資訊

  •  center | 600px

  • Label: 用於AdManagerInterstitialAd.load()

  • Class Name: com.taiwanmobile.pt.gam.mediation.TAmediaGAMCustomEvent

  • Parameter: TAmedia廣告版位



  • 原生(Native)

    center | 600px
  • 名稱: GAM_Mediation_Android_Native

  • 大小: 自訂顯示

  • center | 800px
  • 新增收益群組

  • center | 1000px
  • 名稱: GAM_Mediation_Android_Native

  • 狀態: 有效

  • 廣告格式: 原生格式

  • center | 1000px
  • 新增收益夥伴

  •  center | 1000px

  • 其他收益夥伴詳細資訊

  •  center | 600px

  • Label: 用於AdLoader.Builder().forNativeAd()

  • Class Name: com.taiwanmobile.pt.gam.mediation.TAmediaGAMCustomEvent

  • Parameter: TAmedia原生廣告參數(下方說明)

  • {
    
      "parameters": {
    
        "adUnitId": "ADUNIT_ID",
    
        "mediaType": "VIDEO",
    
        "videoStartUnmuted":true,
    
        "videoCustomControlRequest":true
    
      }
    
    }
    {
    
      "parameters": {
    
        "adUnitId": "ADUNIT_ID",
    
        "mediaType": "BIG_IMAGE"
    
      }
    
    }
    {
    
      "parameters": {
    
        "adUnitId": "ADUNIT_ID",
    
        "mediaType": "SMALL_IMAGE"
    
      }
    
    }



    Gradle設定

    // =======================================================================//
    
    // Google Play Service - ADS
    
    // =======================================================================//
    
    implementation 'com.google.android.gms:play-services-ads:22.2.0'
    
    
    
    // =======================================================================//
    
    // MADP SDK
    
    // =======================================================================//
    
    implementation fileTree(include: ['*.aar'], dir: 'libs')
    
    
    
    // =======================================================================//
    
    // MADP SDK dependencies
    
    // =======================================================================//
    
    // kotlin
    
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.21'
    
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
    
    // retrofit
    
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
    
    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
    
    // advertising ID
    
    implementation 'com.google.android.gms:play-services-ads-identifier:18.0.1'
    
    // appset
    
    implementation 'com.google.android.gms:play-services-appset:16.0.2'
    
    // gson
    
    implementation 'com.google.code.gson:gson:2.10.1'
    
    // lifecycle
    
    def lifecycle_version = "2.6.1"
    
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
    
    implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version"
    
    // viewModels
    
    implementation 'androidx.activity:activity-ktx:1.7.2'
    
    // EncryptedSharedPreferences
    
    implementation 'androidx.security:security-crypto:1.1.0-alpha06'



    Proguard設定

    避免TAmedia Mediation Class Name被被混淆導致Google Ad Manager無法找到中介實作, 請將下列內容加入 proguard-rules.pro

    -keep class com.taiwanmobile.pt.adp.mediation.** {
    
        public protected <fields>;
    
        public protected <methods>;
    
    }
    
    -keep class com.taiwanmobile.pt.gam.mediation.** {
    
        public protected <fields>;
    
        public protected <methods>;
    
    }
    
    -dontwarn com.google.errorprone.annotations.**



    TAmedia中介程式


     center | 600px
    *

    請確認TAmedia SDK 在libs目錄

     center | 600px
    *

    請再次檢查Gradle設定有參考其TAmedia SDK aar檔案

    center | 600px

    橫幅(Banner)

    請參考TAmediaGAMCustomEvent.loadBannerAd(), 此為橫幅中介程式進入點

        override fun loadBannerAd(
    
            configuration: MediationBannerAdConfiguration,
    
            callback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>
    
        ) {
    
            bannerLoader = TAmediaGAMBannerLoader(configuration, callback)
    
            bannerLoader?.loadAd()
    
        }

    插頁(Interstitial)

    請參考TAmediaGAMCustomEvent.loadInterstitialAd(), 此為插頁中介程式進入點

        override fun loadInterstitialAd(
    
            configuration: MediationInterstitialAdConfiguration,
    
            callback: MediationAdLoadCallback<MediationInterstitialAd, MediationInterstitialAdCallback>
    
        ) {
    
            interstitialLoader = TAmediaGAMInterstitialLoader(configuration, callback)
    
            interstitialLoader?.loadAd()
    
        }

    原生(Native)

    請參考TAmediaGAMCustomEvent.loadNativeAd(), 此為原生中介程式進入點

       override fun loadNativeAd(
    
            configuration: MediationNativeAdConfiguration,
    
            callback: MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback>
    
        ) {
    
            nativeLoader = TAmediaGAMNativeLoader(configuration, callback)
    
            nativeLoader?.loadAd()
    
        }



    開發者程式

    請參考 com.taiwanmobile.pt.guide.gam 相關程式碼

     center | 600px
    === 橫幅(Banner) ===

    請參考GAMBannerActivity.kt, 使用AdManagerAdView載入AdManagerAdRequest, 進行廣告請求

        adUnitId?.let {
    
            val request = AdManagerAdRequest.Builder().build()
    
            adManagerAdView = AdManagerAdView(this@GAMBannerActivity)
    
            adManagerAdView?.adUnitId = it
    
            adManagerAdView?.setAdSizes(adSize)
    
            adManagerAdView?.adListener = object: AdListener() {
    
                override fun onAdLoaded() {}
    
                override fun onAdFailedToLoad(adError : LoadAdError) {}
    
                override fun onAdClicked() {}
    
                override fun onAdImpression() {}
    
            }
    
            adManagerAdView?.loadAd(request)
    
            // add view into layout
    
            binding.adContainer.addView(adManagerAdView)
    
        }

    插頁(Interstitial)

    請參考GAMInterstitialActivity.kt, 使用AdManagerInterstitialAd載入AdManagerAdRequest物件, 進行廣告請求

        adUnitId?.let {
    
            val adRequest = AdManagerAdRequest.Builder().build()
    
            AdManagerInterstitialAd.load(this, it, adRequest, object : AdManagerInterstitialAdLoadCallback() {
    
                override fun onAdFailedToLoad(adError: LoadAdError) {}
    
                override fun onAdLoaded(ad: AdManagerInterstitialAd) {
    
                    interstitialAd = ad
    
                    interstitialAd?.show(this@GAMInterstitialActivity)
    
                }
    
            })
    
        }

    原生(Native)

    請參考GAMNativeActivity.kt, 使用AdLoader.forNativeAd()載入AdManagerAdRequest物件, 進行廣告請求

        val adUnitId = args.getString(GAMMainActivity.KEY_ADUNITID) ?: ""
    
        val adLoader = AdLoader.Builder(this, adUnitId)
    
            .forNativeAd { ad: NativeAd ->
    
            if (isDestroyed) {
    
                ad.destroy()
    
                return@forNativeAd
    
            }
    
            nativeAd = ad
    
            val vb = NativeAdBinding.inflate(layoutInflater)
    
                populateNativeAdView(ad, vb)
    
                binding.nativeContainer.removeAllViews()
    
                binding.nativeContainer.addView(vb.root)
    
            }
    
            .withAdListener(object : AdListener() {
    
                override fun onAdFailedToLoad(adError: LoadAdError) {}
    
                override fun onAdClicked() {}
    
                override fun onAdImpression() {}
    
            })
    
            .withNativeAdOptions(NativeAdOptions.Builder().build())
    
            .build()
    
        adLoader.loadAd(AdManagerAdRequest.Builder().build())

    請參考GAMNativeActivity.kt, 在populateNativeAdView()有填充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.mediaView?.mediaContent = nativeAd.mediaContent
    
            nativeAdView.setNativeAd(nativeAd)
    
        }

    請參考NativeAdBinding佈局細節, 使用NativeAdView設計原生廣告佈局, 使用MediaView顯示 影片 或 大圖 或 小圖 /p>

    <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">
    
    
    
        <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" />
    
    
    
        <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" />
    
    
    
        <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" />
    
    
    
        <Button
    
            android:id="@+id/ad_call_to_action"
    
            android:layout_width="wrap_content"
    
            android:layout_height="wrap_content"
    
            android:gravity="center"
    
            android:textSize="12sp" />
    
    
    
    </com.google.android.gms.ads.nativead.NativeAdView>

    長標題 / 短標題設定, 請調整TAmediaGAMNativeAdMapper.kt實作, 將headline設為指定的標題即可

        // Mapping TWMNativeAd to AdMob Native AD resource
    
        // headline by longSubject
    
        nativeAd.nativeAdContent.longSubject?.let { headline = it }
    
        //nativeAd.nativeAdContent.shortSubject?.let { headline = it }



    使用詳細範例

    下載中介程式

    下載連結

    修改 - AndroidManifest.xml


     center | 800px

     center | 800px

    修改 - build.gradle


     center | 800px

     center | 800px

    修改 - 廣告單元


     center | 800px

    *

    修改GAMMainActivity中定義的廣告單元 (ex. /ACCOUNT_ID/TEST_AD_UNIT )

     center | 800px

    範例程式主畫面, 左邊按鈕為AdMob程式範例, 右邊按鈕為Ad Manager程式範例, 請點選右邊Ad Manager

    範例程式

    主選單

    Ad Manager

    200px
    200px


    === 橫幅(Banner) ===

    橫幅(Banner)

    320x50

    300x250

    200px
    200px


    === 插頁(Interstitial) ===

    插頁(Interstitial)

    Interstitial

    Interstitial

    200px
    200px


    === 原生(Native) ===

    原生(Native)

    NATIVE

    NATIVE IMAGE

    200px
    200px



    回首頁