在 Android 應用程式加入原生廣告

原生廣告 API 可讓您針對自家應用程式中顯示的廣告,打造自訂的體驗。使用原生廣告 API 時,您不會收到立即可供展示的廣告,而是會收到如標題、圖像、呼籲字句等的一組廣告屬性,而您需要使用這些屬性來建構用來顯示廣告的自訂檢視畫面。

確保您在開始操作前,已經先行參閱 Audience Network 新手指南Android 新手指南

在本指南中,我們會執行以下原生廣告版位。您將使用下列元件來建立原生廣告:

檢視畫面 #1:廣告圖示

檢視畫面 #2:廣告標題

檢視畫面 #3:贊助標籤

檢視畫面 #4:AdOptionsView

檢視畫面 #5:MediaView

檢視畫面 #6:社交情境

檢視畫面 #7:廣告正文

檢視畫面 #8:呼籲字句按鈕




原生廣告步驟

第 1 步:要求取得原生廣告

第 2 步:建立原生廣告版面配置

第 3 步:使用廣告的中繼資料產生版面配置

第 4 步:使用 MediaView

第 5 步:在不使用自動快取的情況下載入廣告

為 Audience Network SDK 執行初始化

Android Audience Network SDK 5.1 版已加入此方法。

若是 5.3.0 或更高版本,您必須初始化 Android 版 Audience Network SDK如欲了解有關初始化 Android 版 Audience Network SDK 的方法,請參閱此文件

在建立廣告物件及載入廣告前,請為 Audience Network SDK 執行初始化。我們建議您在啟動應用程式時執行此動作。

public class YourApplication extends Application {
    ...
    @Override
    public void onCreate() {
        super.onCreate();
        // Initialize the Audience Network SDK
        AudienceNetworkAds.initialize(this);       
    }
    ...
}

第 1 步:要求取得原生廣告

在您的 Activity 頂端加入下列程式碼,以匯入 Facebook 廣告 SDK:

import com.facebook.ads.*;

然後,將 NativeAd 物件實例化並建立 NativeAdListener,然後以廣告接聽程式呼叫 loadAd()

private final String TAG = "NativeAdActivity".getClass().getSimpleName();
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object.
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        @Override
        public void onMediaDownloaded(Ad ad) {
            // Native ad finished downloading all assets
            Log.e(TAG, "Native ad finished downloading all assets.");
        }

        @Override
        public void onError(Ad ad, AdError adError) {
        // Native ad failed to load
            Log.e(TAG, "Native ad failed to load: " + adError.getErrorMessage());
        }

        @Override
        public void onAdLoaded(Ad ad) {
            // Native ad is loaded and ready to be displayed
            Log.d(TAG, "Native ad is loaded and ready to be displayed!");
        }

        @Override
        public void onAdClicked(Ad ad) {
            // Native ad clicked
            Log.d(TAG, "Native ad clicked!");
        }

        @Override
        public void onLoggingImpression(Ad ad) {
            // Native ad impression
            Log.d(TAG, "Native ad impression logged!");
        }
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());
}

我們將稍後回到這個步驟,將程式碼加入 onAdLoaded() 方法。

第 2 步:建立原生廣告版面配置

下一步是擷取廣告中繼資料,然後使用其屬性來建立自訂的原生用戶介面。您可在配置 .xml 中建立自訂檢視畫面,或在程式碼中加入素材。

設計您應用程式中的原生廣告時,請參閱我們的原生廣告指南

在您 Activity 的版面 activity_main.xml 中,為您的 Native Ad 加入容器。此容器應該為 com.facebook.ads.NativeAdLayout,它是除了 FrameLayout 之外的包裝函式,當中具備一些額外的功能,使我們能夠在廣告之上呈現原生廣告分析報告流程。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:paddingTop="50dp">
    ...
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="50dp">

        <com.facebook.ads.NativeAdLayout
             android:id="@+id/native_ad_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical" />
     </ScrollView>
    ...
</RelativeLayout>

為您的原生廣告建立自訂版面 native_ad_layout.xml



以下是原生廣告的自訂版面範例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ad_unit"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:paddingLeft="10dp"
    android:paddingRight="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
        android:paddingTop="10dp">

        <com.facebook.ads.MediaView
            android:id="@+id/native_ad_icon"
            android:layout_width="35dp"
            android:layout_height="35dp" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingLeft="5dp"
            android:paddingRight="5dp">

        <TextView
            android:id="@+id/native_ad_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:textColor="@android:color/black"
            android:textSize="15sp" />

        <TextView
            android:id="@+id/native_ad_sponsored_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:lines="1"
            android:textColor="@android:color/darker_gray"
            android:textSize="12sp" />

    </LinearLayout>

    <LinearLayout
        android:id="@+id/ad_choices_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end"
        android:orientation="horizontal" />

    </LinearLayout>

    <com.facebook.ads.MediaView
        android:id="@+id/native_ad_media"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:orientation="vertical">

            <TextView
                android:id="@+id/native_ad_social_context"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:lines="1"
                android:textColor="@android:color/darker_gray"
                android:textSize="12sp" />

            <TextView
                android:id="@+id/native_ad_body"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ellipsize="end"
                android:gravity="center_vertical"
                android:lines="2"
                android:textColor="@android:color/black"
                android:textSize="12sp" />

        </LinearLayout>

        <Button
            android:id="@+id/native_ad_call_to_action"
            android:layout_width="100dp"
            android:layout_height="30dp"
            android:layout_gravity="center_vertical"
            android:layout_weight="1"
            android:background="#4286F4"
            android:paddingLeft="3dp"
            android:paddingRight="3dp"
            android:textColor="@android:color/white"
            android:textSize="12sp"
            android:visibility="gone" />

    </LinearLayout>

</LinearLayout>

第 3 步:使用廣告的中繼資料產生版面配置

情境 1:在廣告成功載入後立即顯示廣告。修改上方的 onAdLoaded() 方法以檢索 Native Ad's 屬性,並以下列方式顯示廣告:

private NativeAdLayout nativeAdLayout;
private LinearLayout adView;
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
        @Override
        public void onAdLoaded(Ad ad) {
            // Race condition, load() called again before last ad was displayed
            if (nativeAd == null || nativeAd != ad) {
                return;
            }
            // Inflate Native Ad into Container
            inflateAd(nativeAd);
        }
        ...
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());
}

private void inflateAd(NativeAd nativeAd) {

    nativeAd.unregisterView();

    // Add the Ad view into the ad container.
    nativeAdLayout = findViewById(R.id.native_ad_container);
    LayoutInflater inflater = LayoutInflater.from(NativeAdActivity.this);
    // Inflate the Ad view.  The layout referenced should be the one you created in the last step.
    adView = (LinearLayout) inflater.inflate(R.layout.native_ad_layout_1, nativeAdLayout, false);
    nativeAdLayout.addView(adView);

    // Add the AdOptionsView
    LinearLayout adChoicesContainer = findViewById(R.id.ad_choices_container);
    AdOptionsView adOptionsView = new AdOptionsView(NativeAdActivity.this, nativeAd, nativeAdLayout);
    adChoicesContainer.removeAllViews();
    adChoicesContainer.addView(adOptionsView, 0);

    // Create native UI using the ad metadata.
    MediaView nativeAdIcon = adView.findViewById(R.id.native_ad_icon);
    TextView nativeAdTitle = adView.findViewById(R.id.native_ad_title);
    MediaView nativeAdMedia = adView.findViewById(R.id.native_ad_media);
    TextView nativeAdSocialContext = adView.findViewById(R.id.native_ad_social_context);
    TextView nativeAdBody = adView.findViewById(R.id.native_ad_body);
    TextView sponsoredLabel = adView.findViewById(R.id.native_ad_sponsored_label);
    Button nativeAdCallToAction = adView.findViewById(R.id.native_ad_call_to_action);

    // Set the Text.
    nativeAdTitle.setText(nativeAd.getAdvertiserName());
    nativeAdBody.setText(nativeAd.getAdBodyText());
    nativeAdSocialContext.setText(nativeAd.getAdSocialContext());
    nativeAdCallToAction.setVisibility(nativeAd.hasCallToAction() ? View.VISIBLE : View.INVISIBLE);
    nativeAdCallToAction.setText(nativeAd.getAdCallToAction());
    sponsoredLabel.setText(nativeAd.getSponsoredTranslation());

    // Create a list of clickable views
    List<View> clickableViews = new ArrayList<>();
    clickableViews.add(nativeAdTitle);
    clickableViews.add(nativeAdCallToAction);

    // Register the Title and CTA button to listen for clicks.
    nativeAd.registerViewForInteraction(
            adView, nativeAdMedia, nativeAdIcon, clickableViews);
}

SDK 會自動記錄展示次數並處理點擊操作。請注意,您必須以 NativeAd 實例註冊廣告檢視畫面,才能啟用有關檢視畫面。若要將檢視畫面的所有廣告素材設為可點擊,請使用以下內容註冊該檢視畫面:

registerViewForInteraction(View view, MediaView adMediaView, MediaView adIconView)

在對 NativeAd 使用 registerViewForInteraction 時,SDK 會檢查呼叫是否在主執行緒上運行,以避免任何爭用情況。我們會使用 Preconditions.checkIsOnMainThread() 來執行檢查。請確保您的執行作業符合此標準,因為如果您嘗試從背景執行緒呼叫 registerViewForInteraction,您的應用程式將會出現當機情況。

情境 2:在廣告成功載入幾秒或幾分鐘過後顯示廣告。顯示廣告前,您應檢查廣告是否已經無效。

如果廣告在載入後沒有立即顯示,開發人員就需要檢查廣告是否已經無效。成功載入後,廣告的有效期為 60 分鐘。如果您顯示了無效廣告,就無法收取款項。請調用 isAdInvalidated() 以驗證廣告。

您應該參考下列思路操作,但是請不要將以下程式碼複製到您的專案中,因為這只是一個範例:

private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");

    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
    };

    // Request an ad
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .build());

    // Here is just an example for displaying the ad with delay
    // Please call this method at appropriate timing in your project
    showNativeAdWithDelay();
}

private void showNativeAdWithDelay() {
    /**
     * Here is an example for displaying the ad with delay;
     * Please do not copy the Handler into your project
     */
    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        public void run() {
            // Check if nativeAd has been loaded successfully
            if(nativeAd == null || !nativeAd.isAdLoaded()) {
                return;
            }
            // Check if ad is already expired or invalidated, and do not show ad if that is the case. You will not get paid to show an invalidated ad.
            if(nativeAd.isAdInvalidated()) {
                return;
            }
            inflateAd(nativeAd); // Inflate NativeAd into a container, same as in previous code examples
        }
    }, 1000 * 60 * 15); // Show the ad after 15 minutes
}

控制可點擊的區域

為了提供更優質的用戶體驗及更卓越的成效,您應時常考慮控制廣告中可點擊的區域,以避免發生用戶意外點擊的情況。若要進一步瞭解空白處不可點擊的相關規定,請參閱 Audience Network SDK 政策頁面。

若要有效控制哪些內容可供點擊,您可以使用 registerViewForInteraction(View view, MediaView adMediaView, MediaView adIconView, List<View> clickableViews) 來註冊可點擊的檢視畫面清單。舉例來說,如果我們只希望前面範例中的廣告標題和呼籲字句按鈕可供點擊,則可以像下面這樣編寫程式碼:

@Override
public void onAdLoaded(Ad ad) {
    ...
    // Create a list of clickable views
    List<View> clickableViews = new ArrayList<>();
    clickableViews.add(nativeAdTitle);
    clickableViews.add(nativeAdCallToAction);

    // Register the Title and CTA button to listen for clicks.
    nativeAd.registerViewForInteraction(
            adView, nativeAdMedia, nativeAdIcon, clickableViews);
    ...
}

若要重複使用檢視畫面以便在不同時間顯示不同廣告,則必須先呼叫 unregisterView(),然後再使用不同的 NativeAd 實例來註冊同一檢視畫面。

執行程式碼後,您應該就可以看到原生廣告:

第 4 步:使用 MediaView

為顯示原生廣告封面圖片,您必須使用可同時顯示圖片和影片素材的 Meta Audience Network MediaView。您可在此處查閱原生影片廣告單位的設計原則。

在預設情況下,圖片和影片素材會在載入原生廣告時全部預先快取,這樣在 nativeAd 完成載入後,MediaView 便可以立即播放影片。

private void loadNativeAd() {
    ...
    nativeAd.loadAd();
}

此外,您可以在載入原生廣告時明確指定 NativeAd.MediaCacheFlag.ALL

private void loadNativeAd() {
    ...
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withMediaCacheFlag(NativeAdBase.MediaCacheFlag.ALL)
                    .build());
}

Audience Network 支援原生廣告的兩個快取選項,您可透過 NativeAd.MediaCacheFlag 列舉來定義:

快取常數 說明

ALL

預先快取所有資料(圖示、圖像與影片),此為預設選項

NONE

不預先快取

載入廣告時,下列屬性會包含部分的值:titleiconcoverImagecallToAction。其他屬性會是空值或空白。請確定您的程式碼是否足以處理這些情況。

若無廣告可顯示,系統會呼叫 onError 並顯示 error.code。如您使用自己自訂的回報或中介層,最好檢查錯誤代碼值以偵測此狀況。您可在發生此狀況時以其他廣告聯盟作為遞補,但請勿在之後立即重新要求廣告。

您可快取接收到的廣告中繼資料,並重複使用長達 1 小時。若在此時段過後才使用中繼資料,便需要發出呼叫以載入新廣告。

第 5 步:在不使用自動快取的情況下載入廣告

  • 我們極力建議您在任何情況下都將影音素材快取功能預設為開啟。但是,我們允許您在 loadAd 方法中使用 MediaCacheFlag.NONE 覆寫預設值。如果您決定覆寫預設影音素材快取,請務必小心操作。
private final String TAG = NativeAdActivity.class.getSimpleName();
private NativeAd nativeAd;

private void loadNativeAd() {
    // Instantiate a NativeAd object. 
    // NOTE: the placement ID will eventually identify this as your App, you can ignore it for
    // now, while you are testing and replace it later when you have signed up.
    // While you are using this temporary code you will only get test ads and if you release
    // your code like this to the Google Play your users will not receive ads (you will get a no fill error).
    nativeAd = new NativeAd(this, "YOUR_PLACEMENT_ID");
    NativeAdListener nativeAdListener = new NativeAdListener() {
        ...
    };

    // Request an ad without auto cache
    nativeAd.loadAd(
            nativeAd.buildLoadAdConfig()
                    .withAdListener(nativeAdListener)
                    .withMediaCacheFlag(NativeAdBase.MediaCacheFlag.NONE)
                    .build());
}
  • 在廣告上成功呼叫 onAdLoaded 後,您可以手動呼叫 downloadMedia 方法,以便在適當時開始下載原生廣告的所有影音素材。
@Override
public void onAdLoaded(Ad ad) {
    if (nativeAd == null || nativeAd != ad) {
        return;
    }

    nativeAd.downloadMedia();
}
  • 最後,您可以呼叫 registerViewForInteraction 方法,並在 onMediaDownloaded 回呼中的影音素材載入完畢時顯示廣告。
@Override
public void onMediaDownloaded(Ad ad) {
    if (nativeAd == null || nativeAd != ad) {
        return;
    }

    inflateAd(nativeAd); // Inflate NativeAd into a container, same as in previous code examples
}

如果您載入的廣告沒有自動快取,而且您未手動呼叫 downloadMedia 以開始下載程序,則系統只會在您呼叫 registerViewForInteraction 後才會開始下載影音素材。您需要載入所有影音素材,這樣才算是一次符合資格的廣告展示。

影片廣告硬件加速

Audience Network 中的影片廣告需要硬件加速顯示才能啟動,否則您的影片畫面可能會出現黑屏。這適用於

  • 原生廣告中的影片廣告創意
  • 插頁廣告中的影片廣告創意
  • 插播影片廣告
  • 獎勵式影片

如果您的 Target API 級別 >=14 (Ice Cream Sandwich, Android 4.0.1),硬件加速就會預設為啟用,但您也可以在應用程式級別或活動級別中啟用此功能。

應用程式級別

在 Android Manifest 檔案中,將下列屬性新增至 <application> 標籤,以啟用整個應用程式的硬件加速:

<application android:hardwareAccelerated="true" ...>

活動級別

如果您只想針對應用程式內的特定活動啟用此功能,請前往 Android Manifest 檔案,將下列功能新增至 <activity> 標籤。下列範例將啟用 AudienceNetworkActivity 的硬件加速功能,以便顯示插頁廣告與獎勵式影片:

<activity android:name="com.facebook.ads.AudienceNetworkActivity" android:hardwareAccelerated="true" .../>

後續步驟

  • 請參閱原生廣告範例指南,了解如何在應用程式中加入原生廣告。

  • 探索我們的程式碼範例,當中示範了如何使用原生廣告。NativeAdSample 包含在 SDK 中,您可在 AudienceNetwork/samples 資料夾中找到有關資料。將該專案匯入到您的整合開發環境,然後在裝置或模擬器上執行。

其他資源

新手指南

Audience Network 入門技術指南

程式碼範例

Audience Network 廣告整合範例

常見問題

Audience Network 常見問題

原生廣告範本

這是個較為輕鬆的原生廣告整合方法