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

出自TAMedia
跳至導覽 跳至搜尋
imported>Wikiuser
 
(未顯示由 2 位使用者於中間所作的 53 次修訂)
行 1: 行 1:
<p style="font-size: 18px;">AdMob網站: https://apps.admob.com/ <br><br></p>
= 詳細範例 =
:<p style="font-size: 18px;">[[媒體:TAMedia_AdMob_Medation_20230407.zip | AdMob 21.5.0 Mediation Project]] (包含橫幅、插頁、原生廣告)</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>


<li><p style="font-size: 18px;">輸入應用程式名稱並選擇平台</p></li>
<li><p style="font-size: 18px;">選擇平台</p></li>
[[ image:admob_application_01.PNG | 800px ]]
[[ image:Admob1.png | 800px ]]
<br><br><br>
<br><br><br>


<li><p style="font-size: 18px;">建立完成,請記下'''應用程式 ID'''</p></li>
<li><p style="font-size: 18px;">接著輸入應用程式名稱</p></li>
[[ image:admob_application_02.PNG | 800px ]]
[[ image:Admob2.png | 800px ]]
<br><br><br>
 
<li><p style="font-size: 18px;">建立完成</p></li>
[[ image:Admob3-1.png | 800px ]]
</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:admob_adunit_00.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:admob_adunit_01.PNG | 800px ]]
[[ image:Admob4.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:admob_adunit_02.PNG | 800px ]]
[[ image:Admob5.png| 1000px ]]
<br><br><br>
<br><br><br>


<li><p style="font-size: 18px;">建立完成,請記下 AdMob 的'''廣告單元ID'''</p></li>
<li><p style="font-size: 18px;">建立完成,請記下 AdMob 的'''廣告單元ID'''</p></li>
[[ image:admob_adunit_03.PNG | 800px ]]
[[ image:Admob6.png | 800px ]]
</ul><br><br><br>
</ul><br><br><br>


= '''新增中介服務群組''' =
= '''新增中介服務群組''' =
<ul>
<ul>
<li><p style="font-size: 18px;">進入 AdMob 網頁選擇 '''中介服務''' > '''新增中介服務群組'''</p></li>
<li><p style="font-size: 18px;">進入 AdMob 網頁選擇 '''中介服務''' > '''新增中介服務群組'''</p></li>
[[ image:admob_medgroup_00.PNG | 800px ]]
[[ image:Admob_m_1.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:admob_medgroup_01.PNG | 800px ]]
[[ image:Admob_m_2.png | 400px ]]
<br><br><br>
<br><br><br>


<li><p style="font-size: 18px;">設定中介群組名稱並點選'''加入廣告單元'''</p></li>
<li><p style="font-size: 18px;">設定中介群組名稱並點選'''加入廣告單元'''</p></li>
[[ image:admob_medgroup_02.PNG | 800px ]]
[[ image:Admob_m_3.png | 1000px ]]
<br><br><br>
<br><br><br>


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


行 59: 行 61:
   <p style="font-size: 18px;">點選'''新增自訂事件''',並設定下列相關資訊:</p>
   <p style="font-size: 18px;">點選'''新增自訂事件''',並設定下列相關資訊:</p>
   <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''': com.taiwanmobile.pt.adp.mediation.adapter.TAmediaCustomEvent </p>
   <p style="font-size: 16px">'''Parameter''': 輸入您的 TAMedia 廣告版位ID </p>
   <p style="font-size: 16px">'''Parameter''': 輸入您的 TAmedia 廣告版位ID </p>
</li>
</li>
[[ image:admob_medgroup_04.PNG | 800px ]]
 
[[ image:Admob_m_5.png | 1000px ]]
<br><br>
<br><br>
[[ image:admob_medgroup_05.PNG | 800px ]]
[[ image:Admob_m_6.png | 1000px ]]
<br><br>
 
= '''TAmedia廣告版位ID''' =
[[ image:Admob_m_9.png | 1000px ]]
<br><br>
<br><br>
[[ image:admob_medgroup_06.PNG | 1200px ]]
 
<p style="font-size: 18px;">點選完成後,中介服務群組的設置便結束</p>
[[ image:Admob_m_8.png | 1200px ]]
</ul>
<br><br><br>
<br><br><br>


<li><p style="font-size: 18px;">點選完成後,中介服務群組的設置便結束</p></li>
= '''程式整合''' =
[[ image:admob_medgroup_07.PNG | 1200px ]]
:<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>
</ul>
:<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;">3. 至詳細範例, 下載'''[[#詳細範例 | AdMob 21.5.0 Mediation Project]]''',並整合下列Mediation Code進開發者專案中</p>
<br><br><br>
<br><br><br>


== '''Mediation Code'''==
Banner / Interstitial / Native等中介實作皆在TAmediaCustomEvent
== '''Proguard'''==
下列mediation class, 開發商於proguard中須進行保護, 避免混淆後找不到該class造成AdMob SDK拋出錯誤訊息


<b><span style="color:#ff0000">Could not load custom event implementation class: com.taiwanmobile.pt.adp.mediation.TAmediaNative, trying Adapter implementation class.</span></b>


= '''程式整合''' =
<source>
-keep class com.taiwanmobile.pt.adp.mediation.** {
    public protected <fields>;
    public protected <methods>;
}
</source>


== '''Getting Started''' ==
== '''Developer Sample Code''' ==
:<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>
=== '''Banner''' ===
:<p style="font-size: 18px;">2. 下載'''[[Download MADP Android SDK | TAMedia Android SDK]]''',並參考'''[[Android Getting Started 3.0 | 開始使用Getting Started]]'''整合TAMedia Android SDK</p>
::<p style="font-size: 18px;">1. 在MainActivity.kt中輸入AdUnit Id</p>
<br><br><br>
    companion object {
        private const val ADUNIT_ID_BANNER_320x50 = "<b>{AdMob Banner AdUnit Id}</b>"
        private const val ADUNIT_ID_BANNER_300x250 = "<b>{AdMob Banner AdUnit Id}</b>"
        private const val ADUNIT_ID_SMART_BANNER = "<b>{AdMob Banner AdUnit Id}</b>"
        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"
    }
::<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)
                }
            }
        }
}


== '''實作 Mediation Code'''==
=== Banner ===
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventBanner</p>
  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.TWMAd;
  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>
  public class TAMediaBanner implements CustomEventBanner {
     
      private static final String TAG = "TAMediaBanner";
     
      private TWMAdView adView = null;
 
      @Override
      public void requestBannerAd(final Context context,
                                  final CustomEventBannerListener customEventBannerListener,
                                  String serverParameter,
                                  AdSize adSize,
                                  MediationAdRequest mediationAdRequest,
                                  Bundle bundle) {
          <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
          Log.d(TAG, "requestBannerAd("+serverParameter+") invoked!!");
 
          adView = new TWMAdView( (Activity) context, convertAdSize(adSize), serverParameter);
          adView.setAdListener(new TWMAdViewListener(){
              @Override
              public void onReceiveAd(TWMAd ad) {
                  ((Activity) context).runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          customEventBannerListener.onAdLoaded(adView);
                      }
                  });
              }
 
              @Override
              public void onFailedToReceiveAd(TWMAd ad, final ErrorCode errorCode) {
                  ((Activity) context).runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          customEventBannerListener.onAdFailedToLoad(convertErrorCode(errorCode));
                      }
                  });
              }
 
              @Override
              public void onPresentScreen(TWMAd ad) {
                  ((Activity) context).runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          customEventBannerListener.onAdOpened();
                          <b>//若您需要在AdMob報表上觀察點擊率, 請加入CustomEventBannerListener.onClick()</b>
                          customEventBannerListener.onAdClicked();
                      }
                  });
 
              }
 
              @Override
              public void onDismissScreen(TWMAd ad) {
                  ((Activity) context).runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          customEventBannerListener.onAdClosed();
                      }
                  });
              }
 
              @Override
              public void onLeaveApplication(TWMAd ad) {
                  ((Activity) context).runOnUiThread(new Runnable() {
                      @Override
                      public void run() {
                          customEventBannerListener.onAdLeftApplication();
                      }
                  });
              }
          });
 
          adView.loadAd(convertAdRequest(mediationAdRequest));
      }
 
      @Override
      public void onDestroy() {
          if(adView != null){
              adView.destroy();
          }
      }
 
      @Override
      public void onPause() {}
 
      @Override
      public void onResume() {}
 
 
      <b>//將AdMob所提供的MediationAdRequest轉換為TWMAdRequest</b>
      private TWMAdRequest convertAdRequest(MediationAdRequest request) {
          TWMAdRequest adRequest = new TWMAdRequest();
          if (request.getBirthday() != null) {
 
              Date bDay = request.getBirthday();
              adRequest.setBirthday(bDay);
 
              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''' ===
::<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 = "<b>{AdMob Interstitial AdUnit Id}</b>"
        private const val ADUNIT_ID_NATIVE = "{AdMob Native AdUnit Id}"
        const val KEY_ADUNITID = "adUnitId"
        const val KEY_ADSIZE = "adSize"
    }


::<p style="font-size: 18px;">2. InterstitialActivity 程式加入Interstitial的宣告, 設定AdUnitId</p>
<source>
class InterstitialActivity : AppCompatActivity() {


=== Interstitial ===
    private var interstitialAd: InterstitialAd? = null
:<p style="font-size: 18px;">依照下列方式實作AdMob所提供的CustomEventInterstitial</p>
    private var adUnitId: String? = null
  package com.taiwanmobile.pt.adp.mediation;
    private lateinit var binding: ActivityInterstitialBinding
 
  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.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>
  public class TAMediaInterstitial implements CustomEventInterstitial {
 
  private TWMInterstitialAd interstitialAd = null;
 
  private static final String TAG ="TAMediaInterstitial";
 
  @Override
  public void requestInterstitialAd(final Context context,
  final CustomEventInterstitialListener customEventInterstitialListener,
  String serverParameter,
  MediationAdRequest mediationAdRequest,
  Bundle bundle) {
  <b>// serverParameter: AdMob 後台設定的 TAMedia Slot ID, 會藉由此參數獲得</b>
  Log.d(TAG, "requestInterstitialAd("+serverParameter+") ");
 
  interstitialAd = new TWMInterstitialAd((Activity)context, serverParameter);
 
  interstitialAd.setAdListener(new TWMAdViewListener() {
 
  @Override
  public void onReceiveAd(TWMAd ad) {
  ((Activity) context).runOnUiThread(new Runnable() {
  @Override
  public void run() {
  customEventInterstitialListener.onAdLoaded();
  }
  });
  }
 
  @Override
  public void onFailedToReceiveAd(TWMAd ad, final ErrorCode errorCode) {
  ((Activity) context).runOnUiThread(new Runnable() {
  @Override
  public void run() {
  customEventInterstitialListener.onAdFailedToLoad(convertErrorCode(errorCode));
  }
  });
  }
 
  @Override
  public void onPresentScreen(TWMAd ad) {
  ((Activity) context).runOnUiThread(new Runnable() {
  @Override
  public void run() {
  customEventInterstitialListener.onAdOpened();
  }
  });
  }
 
  @Override
  public void onDismissScreen(TWMAd ad) {
  ((Activity) context).runOnUiThread(new Runnable() {
  @Override
  public void run() {
  customEventInterstitialListener.onAdClosed();
  }
  });
  }
 
  @Override
  public void onLeaveApplication(TWMAd ad) {
  ((Activity) context).runOnUiThread(new Runnable() {
  @Override
  public void run() {
  customEventInterstitialListener.onAdLeftApplication();
  }
  });
  }
 
  });
 
  interstitialAd.loadAd(convertAdRequest(mediationAdRequest));
  }
 
  @Override
  public void showInterstitial() {
  if (interstitialAd != null) {
  interstitialAd.show();
  }
  }
 
  @Override
  public void onDestroy() {}
 
  @Override
  public void onPause() {}
 
  @Override
  public void onResume() {}
 
  <b>//將AdMob所提供的MediationAdRequest轉換為TWMAdRequest</b>
  private TWMAdRequest convertAdRequest(MediationAdRequest request) {
  TWMAdRequest adRequest = new TWMAdRequest();
  if (request.getBirthday() != null) {
 
  Date bDay = request.getBirthday();
  adRequest.setBirthday(bDay);
 
  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>//將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>


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


        val args = intent.extras
        if (args != null) {
            adUnitId = args.getString(MainActivity.KEY_ADUNITID)
        }
    }


    // triggered in activity_int.xml
    fun fireAd(v: View?) {
        adUnitId?.let {
            val adRequest = AdRequest.Builder().build()
            InterstitialAd.load(this, it, adRequest, object : InterstitialAdLoadCallback() {
                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    this@InterstitialActivity.interstitialAd = interstitialAd
                    Toast.makeText(
                        baseContext,
                        "onAdLoaded(interstitial) invoked!!",
                        Toast.LENGTH_SHORT
                    ).show()
                    interstitialAd.show(this@InterstitialActivity)
                }
                override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                    Toast.makeText(
                        baseContext,
                        loadAdError.message,
                        Toast.LENGTH_SHORT
                    ).show()
                    interstitialAd = null
                }
            })
        }
    }
}
</source>




== '''範例程式碼''' ==
:<p style="font-size: 18px;">[[媒體:TAMedia_-_AdMob_Medation_20190926.zip  | Download Sample Code]]</p>
::<p style="font-size: 16px;">※註: 範例專案需要在 '''AndroidManifest.xml''' 和 '''MainActivity.java''' 內分別輸入AdMob的 '''應用程式ID''' 與 '''廣告單元ID''' </p>
<br><br>
<br><br>
:<p style="font-size: 18px;">以下以Banner為例:</p>
=== '''Native''' ===
::<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 = "{AdMob Banner AdUnit Id}"
    android:layout_width="wrap_content"
        private const val ADUNIT_ID_BANNER_300x250 = "{AdMob Banner AdUnit Id}"
    android:layout_height="wrap_content" />
        private const val ADUNIT_ID_SMART_BANNER = "{AdMob Banner AdUnit Id}"
::<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 = "<b>{AdMob Native AdUnit Id}</b>"
    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;">程式內的<b><AdMob Banner Ad Unit ID></b>為 '''[[#新增廣告單元|新增廣告單元]]''' 最後取得的AdMob廣告單元ID</p>
<br><br><br>


::<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, 使用AdMob com.google.android.gms.ads.nativead.NativeAdView</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">
            <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.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>
::<p style="font-size: 18px;">5. 設計架構圖</p>
:::<p style="font-size: 18px;">- 藍色為TAmedia SDK原生廣告類別, 黃色為AdMob SDK原生廣告類別</p>
:::<p style="font-size: 18px;">- 開發者僅需在native_ad.xml使用AdMob SDK, 其他則由TAmedia mediation實作負責</p>
:::<p style="font-size: 18px;">- 佈局中如果有發現AdMob SDK MediaView, TAmedia SDK TWMMediaView則會主動覆蓋至上面, 負責顯示影音廣告</p>
[[ image:AdMob_Mediation_SI_20220425.png | 1000px ]]
== '''AdMob SDK 21.5.0 設定調整''' ==
<p style="font-size: 18px;">中介程式改為TAmediaCustomEvent (Adapter)</p>
<p style="font-size: 18px;">將CustomEventBanner / CustomEventInterstitial / CustomEventNative改為TAmediaCustomEvent</p>
[[ image:AdMob_Mediation_21_5_0_Setup_20230307_03.png | 1000px ]]
<p style="font-size: 18px;">Banner / Interstitial / Native等中介實作皆在TAmediaCustomEvent</p>
[[ image:AdMob_Mediation_22_2_0_Setup_20230717_01.png | 1000px ]]
== '''AdMob SDK 22.2.0 設定調整''' [[檔案:new-xxl.png|30px]]==
*<p style="font-size: 18px;">支援AdMob SDK 22.2.0</p>
*<p style="font-size: 18px;">支援Google Ad Manager</p>
**<p style="font-size: 18px;">[[支援Google Ad Manager| Android Integeration with Ad Manager Mediation]]</p>


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

於 2023年8月8日 (二) 01:50 的最新修訂

詳細範例

AdMob 21.5.0 Mediation Project (包含橫幅、插頁、原生廣告)

新增應用程式

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: com.taiwanmobile.pt.adp.mediation.adapter.TAmediaCustomEvent

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

  • Admob m 5.png

    Admob m 6.png

    TAmedia廣告版位ID

    Admob m 9.png

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

    Admob m 8.png




程式整合

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

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

3. 至詳細範例, 下載 AdMob 21.5.0 Mediation Project,並整合下列Mediation Code進開發者專案中




Mediation Code

Banner / Interstitial / Native等中介實作皆在TAmediaCustomEvent

Proguard

下列mediation class, 開發商於proguard中須進行保護, 避免混淆後找不到該class造成AdMob SDK拋出錯誤訊息

Could not load custom event implementation class: com.taiwanmobile.pt.adp.mediation.TAmediaNative, trying Adapter implementation class.

-keep class com.taiwanmobile.pt.adp.mediation.** {
    public protected <fields>;
    public protected <methods>;
}

Developer Sample Code

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

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. InterstitialActivity 程式加入Interstitial的宣告, 設定AdUnitId

class InterstitialActivity : AppCompatActivity() {

    private var interstitialAd: InterstitialAd? = null
    private var adUnitId: String? = null
    private lateinit var binding: ActivityInterstitialBinding

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

        val args = intent.extras
        if (args != null) {
            adUnitId = args.getString(MainActivity.KEY_ADUNITID)
        }
    }

    // triggered in activity_int.xml
    fun fireAd(v: View?) {
        adUnitId?.let {
            val adRequest = AdRequest.Builder().build()
            InterstitialAd.load(this, it, adRequest, object : InterstitialAdLoadCallback() {
                override fun onAdLoaded(interstitialAd: InterstitialAd) {
                    this@InterstitialActivity.interstitialAd = interstitialAd
                    Toast.makeText(
                        baseContext,
                        "onAdLoaded(interstitial) invoked!!",
                        Toast.LENGTH_SHORT
                    ).show()
                    interstitialAd.show(this@InterstitialActivity)
                }

                override fun onAdFailedToLoad(loadAdError: LoadAdError) {
                    Toast.makeText(
                        baseContext,
                        loadAdError.message,
                        Toast.LENGTH_SHORT
                    ).show()
                    interstitialAd = null
                }
            })
        }
    }
}




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, 使用AdMob com.google.android.gms.ads.nativead.NativeAdView

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

5. 設計架構圖

- 藍色為TAmedia SDK原生廣告類別, 黃色為AdMob SDK原生廣告類別

- 開發者僅需在native_ad.xml使用AdMob SDK, 其他則由TAmedia mediation實作負責

- 佈局中如果有發現AdMob SDK MediaView, TAmedia SDK TWMMediaView則會主動覆蓋至上面, 負責顯示影音廣告

AdMob Mediation SI 20220425.png

AdMob SDK 21.5.0 設定調整

中介程式改為TAmediaCustomEvent (Adapter)

將CustomEventBanner / CustomEventInterstitial / CustomEventNative改為TAmediaCustomEvent

AdMob Mediation 21 5 0 Setup 20230307 03.png

Banner / Interstitial / Native等中介實作皆在TAmediaCustomEvent

AdMob Mediation 22 2 0 Setup 20230717 01.png

AdMob SDK 22.2.0 設定調整 New-xxl.png



回首頁