「Android Integeration with AdMob MediationˍSDK8」修訂間的差異

出自TAMedia
跳至導覽 跳至搜尋
imported>Wikiuser
imported>Wikiuser
 
(未顯示同一使用者於中間所作的 37 次修訂)
行 1: 行 1:
<p style="font-size: 18px;">AdMob網站: https://apps.admob.com/ <br><br></p>
詳細範例:
:<p style="font-size: 18px;">[[媒體:TAMedia_AdMob_Medation_20220210.zip | AdMob 20.5.0 Mediation Project]] (包含橫幅、插頁、原生廣告)。[[檔案:new-xxl.png|30px]]</p>


= '''新增應用程式''' =
= '''新增應用程式''' =
<p style="font-size: 18px;">AdMob網站: https://apps.admob.com/ </p>
<ul>
<ul>
<li><p style="font-size: 18px;">進入 AdMob 網頁選擇 '''應用程式''' > '''新增應用程式'''</p></li>
<li><p style="font-size: 18px;">進入 AdMob 網頁選擇 '''應用程式''' > '''新增應用程式'''</p></li>
[[ image:admob_application_00.PNG | 600px ]]
[[ image:Admob0.png | 500px ]]
<br><br><br>
<br><br><br>


行 19: 行 21:
</ul>
</ul>
<br><br><br>
<br><br><br>


= '''新增廣告單元''' =
= '''新增廣告單元''' =
<ul>
<ul>
<li><p style="font-size: 18px;">點選先前建立的應用程式並選擇 '''廣告單元''' > '''開始匯入'''</p></li>
<li><p style="font-size: 18px;">點選先前建立的應用程式並選擇 '''廣告單元''' > '''開始匯入'''</p></li>
[[ image:Admob3-2.png | 1000px ]]
[[ image:Admob3-2.png | 800px ]]
<br><br><br>
<br><br><br>


<li><p style="font-size: 18px;">選擇欲建立的廣告單元 (以'''橫幅廣告'''為例)</p></li>
<li><p style="font-size: 18px;">選擇欲建立的廣告單元 (以'''橫幅廣告'''為例)</p></li>
[[ image:Admob4.png | 1000px ]]
[[ image:Admob4.png | 800px ]]
<br><br><br>
<br><br><br>


行 38: 行 39:
[[ image:Admob6.png | 800px ]]
[[ image:Admob6.png | 800px ]]
</ul><br><br><br>
</ul><br><br><br>


= '''新增中介服務群組''' =
= '''新增中介服務群組''' =
行 64: 行 62:
   <p style="font-size: 16px">'''有效千次曝光出價''': 越高代表該家聯播網廣告曝光的機會越高</p>
   <p style="font-size: 16px">'''有效千次曝光出價''': 越高代表該家聯播網廣告曝光的機會越高</p>
   <p style="font-size: 16px">'''Class Name''': 根據您的專案輸入 mediation code 的 package name,如: com.taiwanmobile.pt.adp.mediation.TAMediaBanner (下方'''[[#實作 Mediation Code|實作 Mediation Code]]'''章節會說明Mediation Code的實作方式)</p>
   <p style="font-size: 16px">'''Class Name''': 根據您的專案輸入 mediation code 的 package name,如: com.taiwanmobile.pt.adp.mediation.TAMediaBanner (下方'''[[#實作 Mediation Code|實作 Mediation Code]]'''章節會說明Mediation Code的實作方式)</p>
   <p style="font-size: 16px">'''Parameter''': 輸入您的 TAMedia 廣告版位ID </p>
   <p style="font-size: 16px">'''Parameter''': 輸入您的 TAmedia 廣告版位ID </p>
</li>
</li>
[[ image:Admob_m_5.png | 1000px ]]
[[ image:Admob_m_5.png | 1000px ]]
<br><br>
<br><br>
[[ image:Admob_m_6.png | 1000px ]]
[[ image:Admob_m_6.png | 1000px ]]
<br><br>
<br><br>
= '''TAmedia廣告版位ID''' =
[[ image:Admob_m_7.png | 1000px ]]
[[ image:Admob_m_7.png | 1000px ]]
<br><br><br>
<br><br><br>
行 79: 行 80:


= '''程式整合''' =
= '''程式整合''' =
 
:<p style="font-size: 18px;">1. 請參考'''[https://developers.google.com/admob/android/quick-start?hl=zh-TW AdMob for Android]''' 網站提供的方式整合Google Ads SDK,此步驟會使用到'''[[#新增應用程式|新增應用程式]]'''所取得的'''應用程式ID'''</p>
== '''Getting Started''' ==
:<p style="font-size: 18px;">2. 下載'''[[Download MADP Android SDK | TAMedia Android SDK]]''',並參考'''[[Android Getting Started SDK8 | 開始使用Getting Started]]''' 整合TAMedia Android SDK</p>
:<p style="font-size: 18px;">1. 請參考'''[https://developers.google.com/admob/android/quick-start?hl=zh-TW AdMob for Android]'''網站提供的方式整合Google Ads SDK,此步驟會使用到'''[[#新增應用程式|新增應用程式]]'''所取得的'''應用程式ID'''</p>
:<p style="font-size: 18px;">2. 下載'''AdMob 20.5.0 Mediation Project''',並整合下列Mediation Code進開發者專案中</p>
:<p style="font-size: 18px;">2. 下載'''[[Download MADP Android SDK | TAMedia Android SDK]]''',並參考'''[[Android Getting Started 3.0 | 開始使用Getting Started]]'''整合TAMedia Android SDK</p>
<br><br><br>
<br><br><br>


 
== '''Mediation Code'''==
== '''實作 Mediation Code'''==
=== Banner ===
=== Banner ===
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventBanner</p>
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventBanner</p>
  package com.taiwanmobile.pt.adp.mediation;
 
 
    package com.taiwanmobile.pt.adp.mediation
  import android.app.Activity;
   
  import android.content.Context;
    import android.app.Activity
  import android.os.Bundle;
    import android.content.Context
  import android.util.Log;
    import android.os.Bundle
 
    import android.util.Log
  import com.google.android.gms.ads.AdRequest;
    import com.google.android.gms.ads.AdRequest
  import com.google.android.gms.ads.AdSize;
    import com.google.android.gms.ads.AdSize
  import com.google.android.gms.ads.mediation.MediationAdRequest;
    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.CustomEventBanner
  import com.google.android.gms.ads.mediation.customevent.CustomEventBannerListener;
    import com.google.android.gms.ads.mediation.customevent.CustomEventBannerListener
  import com.taiwanmobile.pt.adp.view.TWMAd;
    import com.taiwanmobile.pt.adp.view.*
  import com.taiwanmobile.pt.adp.view.TWMAdRequest;
  import com.taiwanmobile.pt.adp.view.TWMAdRequest.ErrorCode;
  import com.taiwanmobile.pt.adp.view.TWMAdSize;
  import com.taiwanmobile.pt.adp.view.TWMAdView;
  import com.taiwanmobile.pt.adp.view.TWMAdViewListener;
 
  import java.util.Calendar;
  import java.util.Date;
    
    
   <b>// 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaBanner註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述</b>
   <b>// 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaBanner註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述</b>
  public class TAMediaBanner implements CustomEventBanner {
    class TAMediaBanner : CustomEventBanner {
     
   
      private static final String TAG = "TAMediaBanner";
        private var adView: TWMAdView? = null
     
   
      private TWMAdView adView = null;
        override fun requestBannerAd(
 
            context: Context,
      @Override
            customEventBannerListener: CustomEventBannerListener,
      public void requestBannerAd(final Context context,
            serverParameter: String?,
                                  final CustomEventBannerListener customEventBannerListener,
            adSize: AdSize,
                                  String serverParameter,
            mediationAdRequest: MediationAdRequest,
                                  AdSize adSize,
            bundle: Bundle?
                                  MediationAdRequest mediationAdRequest,
        ) {
                                  Bundle bundle) {
            <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
          <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
            Log.d(TAG, "requestBannerAd($serverParameter) invoked!!")
          Log.d(TAG, "requestBannerAd("+serverParameter+") invoked!!");
            adView = TWMAdView(context as Activity, convertAdSize(adSize), serverParameter)
 
            adView?.adListener = object : TWMAdViewListener {
          adView = new TWMAdView( (Activity) context, convertAdSize(adSize), serverParameter);
                override fun onReceiveAd(ad: TWMAd) {
          adView.setAdListener(new TWMAdViewListener(){
                    customEventBannerListener.onAdLoaded(adView)
              @Override
                }
              public void onReceiveAd(TWMAd ad) {
   
                  ((Activity) context).runOnUiThread(new Runnable() {
                override fun onFailedToReceiveAd(ad: TWMAd, errorCode: TWMAdRequest.ErrorCode) {
                      @Override
                    customEventBannerListener.onAdFailedToLoad(
                      public void run() {
                        convertErrorCode(errorCode)
                          customEventBannerListener.onAdLoaded(adView);
                    )
                      }
                }
                  });
   
              }
                override fun onPresentScreen(ad: TWMAd) {
 
                    customEventBannerListener.onAdOpened()
              @Override
                }
              public void onFailedToReceiveAd(TWMAd ad, final ErrorCode errorCode) {
   
                  ((Activity) context).runOnUiThread(new Runnable() {
                override fun onDismissScreen(ad: TWMAd) {
                      @Override
                    customEventBannerListener.onAdClosed()
                      public void run() {
                }
                          customEventBannerListener.onAdFailedToLoad(convertErrorCode(errorCode));
   
                      }
                override fun onLeaveApplication(ad: TWMAd) {
                  });
                    customEventBannerListener.onAdClicked()
              }
                    customEventBannerListener.onAdLeftApplication()
 
                }
              @Override
            }
              public void onPresentScreen(TWMAd ad) {
            adView?.loadAd(TWMAdRequest())
                  ((Activity) context).runOnUiThread(new Runnable() {
        }
                      @Override
   
                      public void run() {
        override fun onDestroy() {
                          customEventBannerListener.onAdOpened();
            adView?.destroy()
                          <b>//若您需要在AdMob報表上觀察點擊率, 請加入CustomEventBannerListener.onClick()</b>
        }
                          customEventBannerListener.onAdClicked();
   
                      }
        override fun onPause() {}
                  });
        override fun onResume() {}
 
   
              }
        <b>//將AdMob的AdSize轉換為TWMAdSize</b>
 
        private fun convertAdSize(adSize: AdSize): TWMAdSize {
              @Override
            return when {
              public void onDismissScreen(TWMAd ad) {
                isAdSizeEqual(adSize, TWMAdSize.BANNER) -> {
                  ((Activity) context).runOnUiThread(new Runnable() {
                    TWMAdSize.BANNER
                      @Override
                }
                      public void run() {
                isAdSizeEqual(adSize, TWMAdSize.BANNER_1200X627) -> {
                          customEventBannerListener.onAdClosed();
                    TWMAdSize.BANNER_1200X627
                      }
                }
                  });
                isAdSizeEqual(adSize, TWMAdSize.BANNER_300X250) -> {
              }
                    TWMAdSize.BANNER_300X250
 
                }
              @Override
                isAdSizeEqual(adSize, TWMAdSize.SMART_BANNER) -> {
              public void onLeaveApplication(TWMAd ad) {
                    TWMAdSize.SMART_BANNER
                  ((Activity) context).runOnUiThread(new Runnable() {
                }
                      @Override
                else -> {
                      public void run() {
                    TWMAdSize.BANNER
                          customEventBannerListener.onAdLeftApplication();
                }
                      }
            }
                  });
        }
              }
   
          });
        private fun isAdSizeEqual(adSize: AdSize, twmAdSize: TWMAdSize): Boolean {
 
            return (adSize.width == twmAdSize.width
          adView.loadAd(convertAdRequest(mediationAdRequest));
                    && adSize.height == twmAdSize.height)
      }
        }
 
   
      @Override
        <b>//將TAMedia ErrorCode轉換為AdMob的ErrorCode</b>
      public void onDestroy() {
        private fun convertErrorCode(errorCode: TWMAdRequest.ErrorCode): Int {
          if(adView != null){
            return when (errorCode) {
              adView.destroy();
                TWMAdRequest.ErrorCode.INTERNAL_ERROR -> {
          }
                    AdRequest.ERROR_CODE_INTERNAL_ERROR
      }
                }
 
                TWMAdRequest.ErrorCode.INVALID_REQUEST -> {
      @Override
                    AdRequest.ERROR_CODE_INVALID_REQUEST
      public void onPause() {}
                }
 
                TWMAdRequest.ErrorCode.NETWORK_ERROR -> {
      @Override
                    AdRequest.ERROR_CODE_NETWORK_ERROR
      public void onResume() {}
                }
 
                TWMAdRequest.ErrorCode.NO_FILL -> {
 
                    AdRequest.ERROR_CODE_NO_FILL
      <b>//將AdMob所提供的MediationAdRequest轉換為TWMAdRequest</b>
                }
      private TWMAdRequest convertAdRequest(MediationAdRequest request) {
                else -> AdRequest.ERROR_CODE_NETWORK_ERROR
          TWMAdRequest adRequest = new TWMAdRequest();
            }
          if (request.getBirthday() != null) {
        }
 
   
              Date bDay = request.getBirthday();
        companion object {
              adRequest.setBirthday(bDay);
            private const val TAG = "TAMediaBanner"
 
        }
              Calendar cal = Calendar.getInstance();
    }
              cal.setTime(bDay);
              adRequest.setAge(getAgeByBirthday(
                      cal.get(Calendar.YEAR),
                      cal.get(Calendar.MONTH),
                      cal.get(Calendar.DATE)));
          }
 
          if (request.getGender() == AdRequest.GENDER_FEMALE) {
              adRequest.setGender(TWMAdRequest.Gender.FEMALE);
          } else if (request.getGender() == AdRequest.GENDER_MALE) {
              adRequest.setGender(TWMAdRequest.Gender.MALE);
          } else {
              adRequest.setGender(TWMAdRequest.Gender.UNKNOWN);
          }
 
          return adRequest;
      }
 
      <b>//將AdMob的AdSize轉換為TWMAdSize</b>
      private TWMAdSize convertAdSize(AdSize adSize) {
          if (isAdSizeEqual(adSize, TWMAdSize.BANNER)) {
              return TWMAdSize.BANNER;
          } else if (isAdSizeEqual(adSize, TWMAdSize.IAB_MRECT)) {
              return TWMAdSize.IAB_MRECT;
          } else if (isAdSizeEqual(adSize, TWMAdSize.IAB_BANNER)) {
              return TWMAdSize.IAB_BANNER;
          } else if (isAdSizeEqual(adSize, TWMAdSize.IAB_LEADERBOARD)) {
              return TWMAdSize.IAB_LEADERBOARD;
          } else if (isAdSizeEqual(adSize, TWMAdSize.IAB_WIDE_SKYSCRAPER)) {
              return TWMAdSize.IAB_WIDE_SKYSCRAPER;
          } else if (isAdSizeEqual(adSize, TWMAdSize.SMART_BANNER)) {
              return TWMAdSize.SMART_BANNER;
          } else {
              return TWMAdSize.BANNER;
          }
      }
 
      private boolean isAdSizeEqual(AdSize adSize, TWMAdSize twmAdSize) {
          return (adSize.getWidth() == twmAdSize.getWidth()
                  && adSize.getHeight() == twmAdSize.getHeight());
      }
 
      <b>//將TAMedia ErrorCode轉換為AdMob的ErrorCode</b>
      private int convertErrorCode(ErrorCode errorCode){
          if(errorCode.equals(ErrorCode.INTERNAL_ERROR)){
              return AdRequest.ERROR_CODE_INTERNAL_ERROR;
          }else if(errorCode.equals(ErrorCode.INVALID_REQUEST)){
              return AdRequest.ERROR_CODE_INVALID_REQUEST;
          }else if(errorCode.equals(ErrorCode.NETWORK_ERROR)){
              return AdRequest.ERROR_CODE_NETWORK_ERROR;
          }else if(errorCode.equals(ErrorCode.NO_FILL)){
              return AdRequest.ERROR_CODE_NO_FILL;
          }else
              return AdRequest.ERROR_CODE_NETWORK_ERROR;
      }
 
      private int getAgeByBirthday(int year, int month, int day){
          Calendar dob = Calendar.getInstance();
          Calendar today = Calendar.getInstance();
 
          dob.set(year, month, day);
 
          int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
          if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)){
              age--;
          }
 
          Integer ageInt = new Integer(age);
          return ageInt.intValue();
      }
 
  }
<br><br>
<br><br>


=== Interstitial ===
=== Interstitial ===
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventInterstitial</p>
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventInterstitial</p>
  package com.taiwanmobile.pt.adp.mediation;
    package com.taiwanmobile.pt.adp.mediation
 
   
  import android.app.Activity;
    import android.app.Activity
  import android.content.Context;
    import android.content.Context
  import android.os.Bundle;
    import android.os.Bundle
  import android.util.Log;
    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.AdRequest;
    import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitial
  import com.google.android.gms.ads.mediation.MediationAdRequest;
    import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitialListener
  import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitial;
    import com.taiwanmobile.pt.adp.view.TWMAd
  import com.google.android.gms.ads.mediation.customevent.CustomEventInterstitialListener;
    import com.taiwanmobile.pt.adp.view.TWMAdRequest
  import com.taiwanmobile.pt.adp.view.TWMAd;
    import com.taiwanmobile.pt.adp.view.TWMAdViewListener
  import com.taiwanmobile.pt.adp.view.TWMAdRequest;
    import com.taiwanmobile.pt.adp.view.TWMInterstitialAd
  import com.taiwanmobile.pt.adp.view.TWMAdRequest.ErrorCode;
  import com.taiwanmobile.pt.adp.view.TWMAdViewListener;
  import com.taiwanmobile.pt.adp.view.TWMInterstitialAd;
 
  import java.util.Calendar;
  import java.util.Date;
    
    
   <b>// 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaInterstitial註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述</b>
   <b>// 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAMediaInterstitial註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述</b>
  public class TAMediaInterstitial implements CustomEventInterstitial {
    class TAMediaInterstitial : CustomEventInterstitial {
 
   
  private TWMInterstitialAd interstitialAd = null;
        private var interstitialAd: TWMInterstitialAd? = null
 
   
  private static final String TAG ="TAMediaInterstitial";
        override fun requestInterstitialAd(
 
            context: Context,
  @Override
            customEventInterstitialListener: CustomEventInterstitialListener,
  public void requestInterstitialAd(final Context context,
            serverParameter: String?,
  final CustomEventInterstitialListener customEventInterstitialListener,
            mediationAdRequest: MediationAdRequest,
  String serverParameter,
            bundle: Bundle?
  MediationAdRequest mediationAdRequest,
        ) {
  Bundle bundle) {
            <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
  <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
            Log.d(TAG, "requestInterstitialAd($serverParameter) ")
  Log.d(TAG, "requestInterstitialAd("+serverParameter+") ");
            interstitialAd = TWMInterstitialAd(context as Activity, serverParameter as String)
 
            interstitialAd?.setAdListener(object : TWMAdViewListener {
  interstitialAd = new TWMInterstitialAd((Activity)context, serverParameter);
   
 
                override fun onReceiveAd(ad: TWMAd) {
  interstitialAd.setAdListener(new TWMAdViewListener() {
                    customEventInterstitialListener.onAdLoaded()
 
                }
  @Override
   
  public void onReceiveAd(TWMAd ad) {
                override fun onFailedToReceiveAd(ad: TWMAd, errorCode: TWMAdRequest.ErrorCode) {
  ((Activity) context).runOnUiThread(new Runnable() {
                    customEventInterstitialListener.onAdFailedToLoad(
  @Override
                        convertErrorCode(errorCode)
  public void run() {
                    )
  customEventInterstitialListener.onAdLoaded();
                }
  }
   
  });
                override fun onPresentScreen(ad: TWMAd) {
  }
                    customEventInterstitialListener.onAdOpened()
 
                }
  @Override
   
  public void onFailedToReceiveAd(TWMAd ad, final ErrorCode errorCode) {
                override fun onDismissScreen(ad: TWMAd) {
  ((Activity) context).runOnUiThread(new Runnable() {
                    customEventInterstitialListener.onAdClosed()
  @Override
                }
  public void run() {
   
  customEventInterstitialListener.onAdFailedToLoad(convertErrorCode(errorCode));
                override fun onLeaveApplication(ad: TWMAd) {
  }
                    customEventInterstitialListener.onAdClicked()
  });
                    customEventInterstitialListener.onAdLeftApplication()
  }
                }
 
            })
  @Override
            interstitialAd?.loadAd(TWMAdRequest())
  public void onPresentScreen(TWMAd ad) {
        }
  ((Activity) context).runOnUiThread(new Runnable() {
   
  @Override
        override fun showInterstitial() {
  public void run() {
            interstitialAd?.show()
  customEventInterstitialListener.onAdOpened();
        }
  }
   
  });
        override fun onDestroy() {}
  }
        override fun onPause() {}
 
        override fun onResume() {}
  @Override
   
  public void onDismissScreen(TWMAd ad) {
        <b>// 將TAMedia ErrorCode轉換為AdMob的ErrorCode</b>
  ((Activity) context).runOnUiThread(new Runnable() {
        private fun convertErrorCode(errorCode: TWMAdRequest.ErrorCode): Int {
  @Override
            return when (errorCode) {
  public void run() {
                TWMAdRequest.ErrorCode.INTERNAL_ERROR -> {
  customEventInterstitialListener.onAdClosed();
                    AdRequest.ERROR_CODE_INTERNAL_ERROR
  }
                }
  });
                TWMAdRequest.ErrorCode.INVALID_REQUEST -> {
  }
                    AdRequest.ERROR_CODE_INVALID_REQUEST
 
                }
  @Override
                TWMAdRequest.ErrorCode.NETWORK_ERROR -> {
  public void onLeaveApplication(TWMAd ad) {
                    AdRequest.ERROR_CODE_NETWORK_ERROR
  ((Activity) context).runOnUiThread(new Runnable() {
                }
  @Override
                TWMAdRequest.ErrorCode.NO_FILL -> {
  public void run() {
                    AdRequest.ERROR_CODE_NO_FILL
  customEventInterstitialListener.onAdLeftApplication();
                }
  }
                else -> AdRequest.ERROR_CODE_NETWORK_ERROR
  });
            }
  }
        }
 
   
  });
        companion object {
 
            private const val TAG = "TAMediaInterstitial"
  interstitialAd.loadAd(convertAdRequest(mediationAdRequest));
        }
  }
    }
 
<br><br>
  @Override
 
  public void showInterstitial() {
=== Native ===
  if (interstitialAd != null) {
 
  interstitialAd.show();
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventNative</p>
  }
::<p style="font-size: 14px;">從AdMob廣告設定serverParameter得知TAmedia原生廣告版位, 進而對TAmedia SDK請求原生廣告, 詳情可參考 [[#TAmedia廣告版位ID|TAmedia廣告版位ID]] </p>
  }
::<p style="font-size: 14px;">下列為附加功能(Optional), 預設關閉, 如需使用再將屬性設為true, 詳情可參考 [http://wiki.tamedia.com.tw/androidDoc/library/com.taiwanmobile.pt.adp.nativead/-t-w-m-native-ad-options/index.html TWMNativeAdOptions] </p>
 
::<p style="font-size: 14px;">videoStartUnmuted: 影片預設開啟聲音</p>
  @Override
::<p style="font-size: 14px;">disableImageLoading: 取消圖片下載, 加速廣告請求</p>
  public void onDestroy() {}
::<p style="font-size: 14px;">videoCustomControlRequest: 取消影片內控制項</p>
 
::<p style="font-size: 14px;">mediaPreferImage: TWMMediaView改呈現圖片</p>
  @Override
 
  public void onPause() {}
<source>
 
 
  @Override
package com.taiwanmobile.pt.adp.mediation
  public void onResume() {}
 
 
import android.content.Context
  <b>//將AdMob所提供的MediationAdRequest轉換為TWMAdRequest</b>
import android.os.Bundle
  private TWMAdRequest convertAdRequest(MediationAdRequest request) {
import com.google.android.gms.ads.mediation.NativeMediationAdRequest
  TWMAdRequest adRequest = new TWMAdRequest();
import com.google.android.gms.ads.mediation.customevent.CustomEventNative
  if (request.getBirthday() != null) {
import com.google.android.gms.ads.mediation.customevent.CustomEventNativeListener
 
import com.taiwanmobile.pt.adp.mediation.native.TANativeEventForwarder
  Date bDay = request.getBirthday();
import com.taiwanmobile.pt.adp.nativead.TWMNativeAdOptions
  adRequest.setBirthday(bDay);
import com.taiwanmobile.pt.adp.view.TWMAdRequest
 
import com.taiwanmobile.pt.adp.view.TWMNativeAd
  Calendar cal = Calendar.getInstance();
 
  cal.setTime(bDay);
// 需將本class的完整類別名稱 com.taiwanmobile.pt.adp.mediation.TAmediaNative註冊於中介服務群組, 如[[ #新增中介服務群組 | 新增中介服務群組 ]]所述
  adRequest.setAge(getAgeByBirthday(
class TAmediaNative : CustomEventNative {
  cal.get(Calendar.YEAR),
 
  cal.get(Calendar.MONTH),
    private var twmNativeAd: TWMNativeAd? = null
  cal.get(Calendar.DATE)));
    // 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
  if (request.getGender() == AdRequest.GENDER_FEMALE) {
    private val disableImageLoading = false
  adRequest.setGender(TWMAdRequest.Gender.FEMALE);
    private val videoCustomControlRequest = false
  } else if (request.getGender() == AdRequest.GENDER_MALE) {
    private val mediaPreferImage = false
  adRequest.setGender(TWMAdRequest.Gender.MALE);
 
  } else {
    override fun onDestroy() {
  adRequest.setGender(TWMAdRequest.Gender.UNKNOWN);
        twmNativeAd?.destroy()
  }
    }
 
 
  return adRequest;
    override fun onPause() {}
  }
 
 
    override fun onResume() {}
  <b>//將TAMedia ErrorCode轉換為AdMob的ErrorCode</b>
 
  private int convertErrorCode(ErrorCode errorCode){
    override fun requestNativeAd(
  if(errorCode.equals(ErrorCode.INTERNAL_ERROR)){
        context: Context,
  return AdRequest.ERROR_CODE_INTERNAL_ERROR;
        customEventNativeListener: CustomEventNativeListener,
  }else if(errorCode.equals(ErrorCode.INVALID_REQUEST)){
        serverParameter: String?,
  return AdRequest.ERROR_CODE_INVALID_REQUEST;
        nativeMediationAdRequest: NativeMediationAdRequest,
  }else if(errorCode.equals(ErrorCode.NETWORK_ERROR)){
        extra: Bundle?
  return AdRequest.ERROR_CODE_NETWORK_ERROR;
    ) {
  }else if(errorCode.equals(ErrorCode.NO_FILL)){
        serverParameter?.let { twmAdUnitId ->
  return AdRequest.ERROR_CODE_NO_FILL;
            twmNativeAd = TWMNativeAd(context, twmAdUnitId).also { nativeAd ->
  }else
                nativeAd.setAdListener(
  return AdRequest.ERROR_CODE_NETWORK_ERROR;
                    TANativeEventForwarder(
  }
                        customEventNativeListener,
 
                        nativeMediationAdRequest.nativeAdRequestOptions
  private int getAgeByBirthday(int year, int month, int day){
                    )
  Calendar dob = Calendar.getInstance();
                )
  Calendar today = Calendar.getInstance();
            }.apply {
 
                val request = TWMAdRequest().apply {
  dob.set(year, month, day);
                    val nativeAdOptions = mutableListOf<TWMNativeAdOptions>()
 
                    if (videoStartUnmuted) {
  int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
                        nativeAdOptions.add(TWMNativeAdOptions.VIDEO_START_UNMUTED)
  if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)){
                    }
  age--;
                    if (disableImageLoading) {
  }
                        nativeAdOptions.add(TWMNativeAdOptions.DISABLE_IMAGE_LOADING)
 
                    }
  Integer ageInt = new Integer(age);
                    if (videoCustomControlRequest) {
  return ageInt.intValue();
                        nativeAdOptions.add(TWMNativeAdOptions.VIDEO_CUSTOM_CONTROLS_REQUESTED)
  }
                    }
  }
                    if (mediaPreferImage) {
<br><br><br>
                        nativeAdOptions.add(TWMNativeAdOptions.MEDIA_PREFER_IMAGE)
                    }
                    if (nativeAdOptions.size > 0) {
                        setNativeAdOptions(nativeAdOptions.toTypedArray())
                    }
                }
                loadAd(request)
            }
        }
    }
 
}
</source>
 
:<p style="font-size: 18px;">依照下列方式實作CustomEventNative需用到的TANativeEventForwarder</p>
<source>
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)
            }
        }
    }
 
}
</source>
 
:<p style="font-size: 18px;">依照下列方式實作TANativeEventForwarder需用到的TANativeAdMapper</p>
<source>
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)
        }
 
    }
}
</source>


:<p style="font-size: 18px;">依照下列方式實作TANativeAdMapper需用到的TANativeMappedImage</p>
<source>
@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
}
</source>


== '''範例程式碼''' ==
== '''Developer Sample Code''' ==
:<p style="font-size: 18px;">[[媒體:TAMedia_-_AdMob_Medation_20190926.zip  | Download Sample Code]]</p>
=== '''Banner''' ===
::<p style="font-size: 16px;">※註: 範例專案需要在 '''AndroidManifest.xml''' 和 '''MainActivity.java''' 內分別輸入AdMob的 '''應用程式ID''' 與 '''廣告單元ID''' </p>
<br><br>
:<p style="font-size: 18px;">以下以Banner為例:</p>
:<p style="font-size: 18px;">以下以Banner為例:</p>
::<p style="font-size: 18px;">1. 在layout檔案中加入可放置廣告的LinearLayout(※僅供參考,開發者可依照自訂的layout進行配置使用)</p>
::<p style="font-size: 18px;">1. 在MainActivity.kt中輸入AdUnit Id</p>
<LinearLayout
    companion object {
    android:id="@+id/Layout_AdView"
        private const val ADUNIT_ID_BANNER_320x50 = "<b>{AdMob Banner AdUnit Id}</b>"
    android:layout_width="wrap_content"
        private const val ADUNIT_ID_BANNER_300x250 = "<b>{AdMob Banner AdUnit Id}</b>"
    android:layout_height="wrap_content" />
         private const val ADUNIT_ID_SMART_BANNER = "<b>{AdMob Banner AdUnit Id}</b>"
::<p style="font-size: 18px;">2. 程式加入Banner的宣告, 設定AdUnitId與AdSize</p>
         private const val ADUNIT_ID_INTERSTITIAL = "{AdMob Interstitial AdUnit Id}"
public class MainActivity extends Activity {
         private const val ADUNIT_ID_NATIVE = "{AdMob Native AdUnit Id}"
    LinearLayout layout = null;
         const val KEY_ADUNITID = "adUnitId"
    @Override
         const val KEY_ADSIZE = "adSize"
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        layout = (LinearLayout) this.findViewById(R.id.Layout_AdView);
         adView = new AdView(this);
        adView.setAdUnitId("<b><AdMob Banner Ad Unit ID></b>");
         adView.setAdSize(AdSize.BANNER);   
         layout.addView(adView);
         AdRequest request = new AdRequest.Builder().build();
         adView.loadAd(request);
     }
     }
::<p style="font-size: 18px;">2. 在layout檔案中加入可放置廣告的RelativeLayout(※僅供參考,開發者可依照自訂的layout進行配置使用)</p>
    <RelativeLayout
        android:id="@+id/adContainer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true">
    </RelativeLayout>
::<p style="font-size: 18px;">3. BannerActivity 程式加入Banner的宣告, 設定AdUnitId與AdSize</p>
    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
                        )
                    }
                } <br>
                // 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)
                }
            }
        }
  }
  }
::<p style="font-size: 18px;">程式內的<b><AdMob Banner Ad Unit ID></b>為 '''[[#新增廣告單元|新增廣告單元]]''' 最後取得的AdMob廣告單元ID</p>
<br><br><br>


<br><br>
=== '''Interstitial''' ===
<br><br>
=== '''Native''' ===
:<p style="font-size: 18px;">以下以Native為例:</p>
::<p style="font-size: 18px;">1. 在MainActivity.kt中輸入AdUnit Id</p>
    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 = "<b>{AdMob Native AdUnit Id}</b>"
        const val KEY_ADUNITID = "adUnitId"
        const val KEY_ADSIZE = "adSize"
    }
::<p style="font-size: 18px;">2. NativeActivity的layout如下, 在layout檔案中加入可放置原生廣告的nativeContainer(※這裡以FrameLayout為例,開發者可依照自訂的layout進行配置使用)</p>
    <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">
    <font size = "+1" color="#ff0000"><FrameLayout</font>
            android:id="@+id/native_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/activity_vertical_margin" />
    </LinearLayout>
::<p style="font-size: 18px;">3. 準備廣告佈局native_ad.xml, 在com.google.android.gms.ads.nativead.NativeAdView上添加<b>TWMNativeAdView</b></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">
        <b><font size = "+1" color="#ff0000"><com.taiwanmobile.pt.adp.view.TWMNativeAdView</font></b>
            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>
        <b><font size = "+1" color="#ff0000"></com.taiwanmobile.pt.adp.view.TWMNativeAdView></font></b>
    </com.google.android.gms.ads.nativead.NativeAdView>
::<p style="font-size: 18px;">4. 使用AdMob AdLoader載入原生廣告</p>
:::<p style="font-size: 18px;">當AdLoader取得原生廣告時, 產出(inflate)原生廣告佈局native_ad.xml並進行NativeAdView物件填充(population), 詳情可參考下方<b>populateNativeAdView()</b></p>
:::<p style="font-size: 18px;">NativeAdView填充下列屬性: headline, body, call to action, icon, mediaView等資訊</p>
:::<p style="font-size: 18px;">填充後將native_ad.xml物件加入nativeContainer</p>
<source>
    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)
    }
</source>


<br>
<br>
<p style="font-size: 18px;">[[Android SDK Developer Guide 2| 回首頁]]</p>
<p style="font-size: 18px;">[[Android SDK Developer Guide 2| 回首頁]]</p>

於 2022年2月11日 (五) 03:28 的最新修訂

詳細範例:

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

新增應用程式

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

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

  • Admob0.png


  • 選擇平台

  • Admob1.png


  • 接著輸入應用程式名稱

  • Admob2.png


  • 建立完成

  • Admob3-1.png




新增廣告單元

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

  • Admob3-2.png


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

  • Admob4.png


  • 輸入廣告單元名稱

  • Admob5.png


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

  • Admob6.png




新增中介服務群組

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

  • Admob m 1.png


  • 設定廣告格式、平台

  • Admob m 2.png


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

  • Admob m 3.png


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

  • Admob m 4.png


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

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

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

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

  • Admob m 5.png

    Admob m 6.png

    TAmedia廣告版位ID

    Admob m 7.png


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

  • Admob m 8.png




程式整合

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



回首頁