「Android Integeration with Ad Manager Mediation」修訂間的差異

出自TAMedia
跳至導覽 跳至搜尋
 
(未顯示同一使用者於中間所作的 67 次修訂)
行 1: 行 1:
== 詳細範例 ==
<p style="font-size: 18px;">[[媒體:TAmedia_Ad_Manager_Medation_20230810.zip | Ad Manager 22.2.0 Mediation Project]] (包含橫幅、插頁、原生廣告)。[[檔案:new-xxl.png|30px]]</p>
<br>
== 新增廣告單元 / 收益群組 ==
== 新增廣告單元 / 收益群組 ==
=== 登入Google Ad Manager ===
=== 登入Google Ad Manager ===
https://admanager.google.com/home/
https://admanager.google.com/home/
<br>
<br>
[[ image:gam_android_00.png | 1000px ]]
[[ image:gam_android_00.png | center | 800px ]]
<br>
<br>


行 9: 行 13:
<ul>
<ul>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
[[ image:gam_banner_00.png | 800px ]]
[[ image:gam_banner_00.png | center | 600px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Banner_320x50</p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Banner_320x50</p></li>
<li><p style="font-size: 18px;">大小: 320x50 </p></li>
<li><p style="font-size: 18px;">大小: 320x50 </p></li>
[[ image:gam_banner_01.png | 800px ]]
[[ image:gam_banner_01.png | center | 800px ]]
<li><p style="font-size: 18px;">新增收益群組</p></li>
<li><p style="font-size: 18px;">新增收益群組</p></li>
[[ image:gam_banner_02.png | 800px ]]
[[ image:gam_banner_02.png | center | 800px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Banner_320x50 </p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Banner_320x50 </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">廣告格式: 橫幅 </p></li>
<li><p style="font-size: 18px;">廣告格式: 橫幅 </p></li>
[[ image:gam_banner_05.png | 800px ]]
[[ image:gam_banner_05.png | center | 1000px ]]
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
[[ image:gam_banner_04.png | 800px ]]
[[ image:gam_banner_04.png | center | 1000px ]]
<br>
<br>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
[[ image:gam_banner_07.png | 800px ]]
[[ image:gam_banner_07.png | center | 600px ]]
<br>
<br>
<li><p style="font-size: 18px;">Label: 用於AdManagerAdView.adUnitId </p></li>
<li><p style="font-size: 18px;">Label: 用於AdManagerAdView.adUnitId </p></li>
行 35: 行 39:
<ul>
<ul>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
[[ image:gam_banner_00.png | 800px ]]
[[ image:gam_banner_00.png | center | 600px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Interstitial</p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Interstitial</p></li>
<li><p style="font-size: 18px;">大小: 1024x768, 768x1024, 480x320, 320x480 </p></li>
<li><p style="font-size: 18px;">大小: 1024x768, 768x1024, 480x320, 320x480 </p></li>
[[ image:gam_interstitial_01.png | 1000px ]]
[[ image:gam_interstitial_01.png | center | 1000px ]]
<li><p style="font-size: 18px;">新增收益群組</p></li>
<li><p style="font-size: 18px;">新增收益群組</p></li>
[[ image:gam_banner_04.png | 1000px ]]
[[ image:gam_banner_04.png | center | 1000px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Interstitial </p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Interstitial </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">廣告格式: 插頁式 </p></li>
<li><p style="font-size: 18px;">廣告格式: 插頁式 </p></li>
[[ image:gam_interstitial_02.png | 1000px ]]
[[ image:gam_interstitial_02.png | center | 1000px ]]
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
[[ image:gam_banner_04.png | 800px ]]
[[ image:gam_banner_04.png | center | 1000px ]]
<br>
<br>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
[[ image:gam_interstitial_03.png | 1000px ]]
[[ image:gam_interstitial_03.png | center | 600px ]]
<br>
<br>
<li><p style="font-size: 18px;">Label: 用於AdManagerInterstitialAd.load() </p></li>
<li><p style="font-size: 18px;">Label: 用於AdManagerInterstitialAd.load() </p></li>
行 61: 行 65:
<ul>
<ul>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
<li><p style="font-size: 18px;">進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元</p></li>
[[ image:gam_banner_00.png | 1000px ]]
[[ image:gam_banner_00.png | center | 600px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Native</p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Native</p></li>
<li><p style="font-size: 18px;">大小: 自訂顯示 </p></li>
<li><p style="font-size: 18px;">大小: 自訂顯示 </p></li>
[[ image:gam_native_01.png | 1000px ]]
[[ image:gam_native_01.png | center | 800px ]]
<li><p style="font-size: 18px;">新增收益群組</p></li>
<li><p style="font-size: 18px;">新增收益群組</p></li>
[[ image:gam_banner_04.png | 1000px ]]
[[ image:gam_banner_04.png | center | 1000px ]]
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Native </p></li>
<li><p style="font-size: 18px;">名稱: GAM_Mediation_Android_Native </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">狀態: 有效 </p></li>
<li><p style="font-size: 18px;">廣告格式: 原生格式 </p></li>
<li><p style="font-size: 18px;">廣告格式: 原生格式 </p></li>
[[ image:gam_native_02.png | 1000px ]]
[[ image:gam_native_02.png | center | 1000px ]]
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
<li><p style="font-size: 18px;">新增收益夥伴</p></li>
[[ image:gam_banner_04.png | 800px ]]
[[ image:gam_banner_04.png | center | 1000px ]]
<br>
<br>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
<li><p style="font-size: 18px;">其他收益夥伴詳細資訊</p></li>
[[ image:gam_native_03.png | 1000px ]]
[[ image:gam_native_03.png | center | 600px ]]
<br>
<br>
<li><p style="font-size: 18px;">Label: 用於AdLoader.Builder().forNativeAd() </p></li>
<li><p style="font-size: 18px;">Label: 用於AdLoader.Builder().forNativeAd() </p></li>
行 82: 行 86:
</ul>
</ul>


*MediaView顯示影音
*<p style="font-size: 18px;">MediaView顯示影音</p>
**adUnitId: TAmedia廣告版位
**<p style="font-size: 16px;">adUnitId: TAmedia廣告版位</p>
**mediaType: VIDEO
**<p style="font-size: 16px;">mediaType: VIDEO</p>
**videoStartUnmuted: 影片聲音預設開關, true: 有聲音, false: 無聲音
**<p style="font-size: 16px;">videoStartUnmuted: 影片聲音預設開關, true: 有聲音, false: 無聲音</p>
**videoCustomControlRequest: 影片上是否要顯示秒數, 靜音, 前往瀏覽等UI按鈕, true: 不顯示, false: 顯示
**<p style="font-size: 16px;">videoCustomControlRequest: 影片上是否要顯示秒數, 靜音, 前往瀏覽等UI按鈕, true: 不顯示, false: 顯示</p>
<pre>
<pre style="font-size: 14px">
{
{
   "parameters": {
   "parameters": {
行 98: 行 102:
</pre>
</pre>


*MediaView顯示大圖(1200x628)
*<p style="font-size: 18px;">MediaView顯示大圖(1200x628)</p>
**adUnitId: TAmedia廣告版位
**<p style="font-size: 16px;">adUnitId: TAmedia廣告版位</p>
**mediaType: BIG_IMAGE
**<p style="font-size: 16px;">mediaType: BIG_IMAGE</p>
<pre>
<pre style="font-size: 14px">
{
{
   "parameters": {
   "parameters": {
行 110: 行 114:
</pre>
</pre>


*MediaView顯示小圖(960x640)
*<p style="font-size: 18px;">MediaView顯示小圖(960x640)</p>
**adUnitId: TAmedia廣告版位
**<p style="font-size: 16px;">adUnitId: TAmedia廣告版位</p>
**mediaType: SMALL_IMAGE
**<p style="font-size: 16px;">mediaType: SMALL_IMAGE</p>
<pre>
<pre style="font-size: 14px">
{
{
   "parameters": {
   "parameters": {
行 120: 行 124:
   }
   }
}
}
</pre>
<br><br>
== Gradle設定 ==
<pre>
// =======================================================================//
// 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'
</pre>
<br><br>
== Proguard設定 ==
<p style="font-size: 18px;">避免TAmedia Mediation Class Name被被混淆導致Google Ad Manager無法找到中介實作, 請將下列內容加入 proguard-rules.pro </p>
<pre>
-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.**
</pre>
<br><br>
== TAmedia中介程式 ==
*<p style="font-size: 18px;">請將com.taiwanmobile.pt.gam.mediation程式碼加入專案, 請確認Google Ad Manager收益群組設定的Class Name與下列一致</p>
*<p style="font-size: 18px;">com.taiwanmobile.pt.gam.mediation.TAmediaGAMCustomEvent</p>
<br>
[[ image:gam_android_mediation_00.png | center | 600px ]]
<br>
*<p style="font-size: 18px;">請確認TAmedia SDK 在libs目錄</p>
[[ image:gam_android_mediation_01.png | center | 600px ]]
<br>
*<p style="font-size: 18px;">請再次檢查Gradle設定有參考其TAmedia SDK aar檔案</p>
[[ image:gam_android_mediation_02.png | center | 600px ]]
===  橫幅(Banner) ===
<p style="font-size: 18px;">請參考TAmediaGAMCustomEvent.loadBannerAd(), 此為橫幅中介程式進入點</p>
<pre style="font-size: 14px">
    override fun loadBannerAd(
        configuration: MediationBannerAdConfiguration,
        callback: MediationAdLoadCallback<MediationBannerAd, MediationBannerAdCallback>
    ) {
        bannerLoader = TAmediaGAMBannerLoader(configuration, callback)
        bannerLoader?.loadAd()
    }
</pre>
=== 插頁(Interstitial) ===
<p style="font-size: 18px;">請參考TAmediaGAMCustomEvent.loadInterstitialAd(), 此為插頁中介程式進入點</p>
<pre style="font-size: 14px">
    override fun loadInterstitialAd(
        configuration: MediationInterstitialAdConfiguration,
        callback: MediationAdLoadCallback<MediationInterstitialAd, MediationInterstitialAdCallback>
    ) {
        interstitialLoader = TAmediaGAMInterstitialLoader(configuration, callback)
        interstitialLoader?.loadAd()
    }
</pre>
</pre>
=== 原生(Native) ===
<p style="font-size: 18px;">請參考TAmediaGAMCustomEvent.loadNativeAd(), 此為原生中介程式進入點</p>
<pre style="font-size: 14px">
  override fun loadNativeAd(
        configuration: MediationNativeAdConfiguration,
        callback: MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback>
    ) {
        nativeLoader = TAmediaGAMNativeLoader(configuration, callback)
        nativeLoader?.loadAd()
    }
</pre>
<br><br>


== 開發者程式 ==
== 開發者程式 ==
<p style="font-size: 18px;">請參考 com.taiwanmobile.pt.guide.gam 相關程式碼</p>
[[ image:gam_android_mediation_03.png | center | 600px ]]
<br>
===  橫幅(Banner) ===
===  橫幅(Banner) ===
<p style="font-size: 18px;">請參考GAMBannerActivity.kt, 使用AdManagerAdView載入AdManagerAdRequest, 進行廣告請求</p>
<pre style="font-size: 14px">
    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)
    }
</pre>


=== 插頁(Interstitial) ===
=== 插頁(Interstitial) ===
<p style="font-size: 18px;">請參考GAMInterstitialActivity.kt, 使用AdManagerInterstitialAd載入AdManagerAdRequest物件, 進行廣告請求</p>
<pre style="font-size: 14px">
    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)
            }
        })
    }
</pre>


=== 原生(Native) ===
=== 原生(Native) ===
<p style="font-size: 18px;">請參考GAMNativeActivity.kt, 使用AdLoader.forNativeAd()載入AdManagerAdRequest物件, 進行廣告請求</p>
<pre style="font-size: 14px">
    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())
</pre>
<p style="font-size: 18px;">請參考GAMNativeActivity.kt, 在populateNativeAdView()有填充NativeAdView實作細節</p>
<pre style="font-size: 14px">
    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)
    }
</pre>
<p style="font-size: 18px;">請參考NativeAdBinding佈局細節, 使用NativeAdView設計原生廣告佈局, 使用MediaView顯示 '''<span style="color:red;">影片</span>''' 或 '''<span style="color:red;">大圖</span>''' 或 '''<span style="color:red;">小圖</span>''' /p>
<pre style="font-size: 14px">
<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>
</pre>
<p style="font-size: 18px;">長標題 / 短標題設定, 請調整TAmediaGAMNativeAdMapper.kt實作, 將headline設為指定的標題即可</p>
<pre style="font-size: 14px">
    // Mapping TWMNativeAd to AdMob Native AD resource
    // headline by longSubject
    nativeAd.nativeAdContent.longSubject?.let { headline = it }
    //nativeAd.nativeAdContent.shortSubject?.let { headline = it }
</pre>


<br><br>
<br><br>


== TAmedia中介程式 ==
== 使用詳細範例 ==
 
=== 下載中介程式 ===
<p style="font-size: 24px;">[[#詳細範例 | 下載連結]]</p>
 
=== 修改 - AndroidManifest.xml ===
*<p style="font-size: 20px;">Google Ad Manager中註冊之應用程式ID (Application ID)</p>
<br>
[[ image:gam_android_02.png | center | 800px ]]
<br><br>
[[ image:gam_android_01.png | center | 800px ]]
<br>
 
=== 修改 - build.gradle ===
*<p style="font-size: 18px;">Google Ad Manager中註冊之套件名稱</p>
<br>
[[ image:gam_android_05.png | center | 800px ]]
<br><br>
[[ image:gam_android_06.png | center | 800px ]]
<br>
 
=== 修改 - 廣告單元 ===
*<p style="font-size: 18px;">Google Ad Manager中註冊之廣告單元</p>
<br>
[[ image:gam_android_04.png | center | 800px ]]
<br><br>
*<p style="font-size: 18px;">修改GAMMainActivity中定義的廣告單元 (ex. <span style="color:#000000; background:#86b953">/ACCOUNT_ID/TEST_AD_UNIT</span> ) </p>
[[ image:gam_android_03.png | center | 800px ]]
<br>
 
<p style="font-size: 18px;">範例程式主畫面, 左邊按鈕為AdMob程式範例, 右邊按鈕為Ad Manager程式範例, 請點選右邊Ad Manager</p>
{| class="wikitable" style="margin:auto"
|+ 範例程式
|-
! 主選單 !! Ad Manager
|-
| [[ image:gam_android_mediation_selector.png | 200px ]] || [[ image:gam_android_mediation_selector_gam.png | 200px ]]
|}
<br>
===  橫幅(Banner) ===
===  橫幅(Banner) ===
 
{| class="wikitable" style="margin:auto"
|+ 橫幅(Banner)
|-
! 320x50 !! 300x250
|-
| [[ image:gam_android_demo_banner.png | 200px ]] || [[ image:gam_android_demo_banner_2.png | 200px ]]
|}
<br>
=== 插頁(Interstitial) ===
=== 插頁(Interstitial) ===
 
{| class="wikitable" style="margin:auto"
|+ 插頁(Interstitial)
|-
! Interstitial !! Interstitial
|-
| [[ image:gam_android_demo_interstitial_01.png | 200px ]] || [[ image:gam_android_demo_interstitial_02.png | 200px ]]
|}
<br>
=== 原生(Native) ===
=== 原生(Native) ===
{| class="wikitable" style="margin:auto"
|+ 原生(Native)
|-
! NATIVE !! NATIVE IMAGE
|-
| [[ image:gam_android_demo_native_01.png | 200px ]] || [[ image:gam_android_demo_native_02.png | 200px ]]
|}


<br><br>
<br><br>
<p style="font-size: 18px;">[[SDK8_Android_SDK_Developer_Guide| 回首頁]]</p>

於 2023年10月11日 (三) 03:19 的最新修訂

詳細範例

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


新增廣告單元 / 收益群組

登入Google Ad Manager

https://admanager.google.com/home/

Gam android 00.png


橫幅(Banner)

  • 進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元

  • Gam banner 00.png
  • 名稱: GAM_Mediation_Android_Banner_320x50

  • 大小: 320x50

  • Gam banner 01.png
  • 新增收益群組

  • Gam banner 02.png
  • 名稱: GAM_Mediation_Android_Banner_320x50

  • 狀態: 有效

  • 廣告格式: 橫幅

  • Gam banner 05.png
  • 新增收益夥伴

  • Gam banner 04.png


  • 其他收益夥伴詳細資訊

  • Gam banner 07.png


  • Label: 用於AdManagerAdView.adUnitId

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

  • Parameter: TAmedia廣告版位




插頁(Interstitial)

  • 進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元

  • Gam banner 00.png
  • 名稱: GAM_Mediation_Android_Interstitial

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

  • Gam interstitial 01.png
  • 新增收益群組

  • Gam banner 04.png
  • 名稱: GAM_Mediation_Android_Interstitial

  • 狀態: 有效

  • 廣告格式: 插頁式

  • Gam interstitial 02.png
  • 新增收益夥伴

  • Gam banner 04.png


  • 其他收益夥伴詳細資訊

  • Gam interstitial 03.png


  • Label: 用於AdManagerInterstitialAd.load()

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

  • Parameter: TAmedia廣告版位




原生(Native)

  • 進入 Ad Manager 網頁選擇 應用單元 -> 新增廣告單元

  • Gam banner 00.png
  • 名稱: GAM_Mediation_Android_Native

  • 大小: 自訂顯示

  • Gam native 01.png
  • 新增收益群組

  • Gam banner 04.png
  • 名稱: GAM_Mediation_Android_Native

  • 狀態: 有效

  • 廣告格式: 原生格式

  • Gam native 02.png
  • 新增收益夥伴

  • Gam banner 04.png


  • 其他收益夥伴詳細資訊

  • Gam native 03.png


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

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

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

  • MediaView顯示影音

    • adUnitId: TAmedia廣告版位

    • mediaType: VIDEO

    • videoStartUnmuted: 影片聲音預設開關, true: 有聲音, false: 無聲音

    • videoCustomControlRequest: 影片上是否要顯示秒數, 靜音, 前往瀏覽等UI按鈕, true: 不顯示, false: 顯示

{
  "parameters": {
    "adUnitId": "ADUNIT_ID",
    "mediaType": "VIDEO",
    "videoStartUnmuted":true,
    "videoCustomControlRequest":true
  }
}
  • MediaView顯示大圖(1200x628)

    • adUnitId: TAmedia廣告版位

    • mediaType: BIG_IMAGE

{
  "parameters": {
    "adUnitId": "ADUNIT_ID",
    "mediaType": "BIG_IMAGE"
  }
}
  • MediaView顯示小圖(960x640)

    • adUnitId: TAmedia廣告版位

    • mediaType: SMALL_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中介程式

  • 請將com.taiwanmobile.pt.gam.mediation程式碼加入專案, 請確認Google Ad Manager收益群組設定的Class Name與下列一致

  • com.taiwanmobile.pt.gam.mediation.TAmediaGAMCustomEvent


Gam android mediation 00.png


  • 請確認TAmedia SDK 在libs目錄

Gam android mediation 01.png


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

Gam android mediation 02.png

橫幅(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 相關程式碼

Gam android mediation 03.png


橫幅(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

  • Google Ad Manager中註冊之應用程式ID (Application ID)


Gam android 02.png



Gam android 01.png


修改 - build.gradle

  • Google Ad Manager中註冊之套件名稱


Gam android 05.png



Gam android 06.png


修改 - 廣告單元

  • Google Ad Manager中註冊之廣告單元


Gam android 04.png



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

Gam android 03.png


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

範例程式
主選單 Ad Manager
Gam android mediation selector.png Gam android mediation selector gam.png


橫幅(Banner)

橫幅(Banner)
320x50 300x250
Gam android demo banner.png Gam android demo banner 2.png


插頁(Interstitial)

插頁(Interstitial)
Interstitial Interstitial
Gam android demo interstitial 01.png Gam android demo interstitial 02.png


原生(Native)

原生(Native)
NATIVE NATIVE IMAGE
Gam android demo native 01.png Gam android demo native 02.png



回首頁