向 Android 应用添加原生横幅广告

原生横幅广告 API 可让您打造显示原生广告的定制化体验,而无需使用广告主的图片、视频或轮播广告内容等创意素材。与原生广告相似,您将收到一组广告属性,例如标题、图标,以及行动号召,并需使用这些属性来构建用于展示广告的自定义视图。然而,与横幅广告不同,原生横幅广告 API 提供原生布局体验,让您可以完全控制广告内组件布局的自定义方式。

请确保先阅读 Audience Network 入门指南Android 入门指南,然后再继续操作。

在本指南中,我们将实施以下原生横幅广告版位。您将创建包含下列组件的原生横幅广告:

图 1:AdOptionsView

图 2:赞助内容标签

图 3:广告图标

图 4:广告标题

图 5:社交元素

图 6:行动号召按钮




创建原生横幅广告的步骤

第 1 步:请求原生横幅广告

第 2 步:创建原生横幅广告布局

第 3 步:利用广告的元数据填充布局

对 Audience Network SDK 进行初始化

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

5.3.0 及以上版本的 Audience Network SDK 需要进行显式初始化。有关如何初始化 Audience Network Android 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.*;

然后对 NativeBannerAd 对象进行实例化,创建 AdListener,并在 Activity 中调用 loadAd(...)

public class NativeBannerAdActivity extends Activity {

    private final String TAG = NativeBannerAdActivity.class.getSimpleName();
    private NativeBannerAd nativeBannerAd;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Instantiate a NativeBannerAd 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).
        nativeBannerAd = new NativeBannerAd(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!");
            }
        });
        // load the ad
        nativeBannerAd.loadAd(
                nativeBannerAd.buildLoadAdConfig()
                        .withAdListener(nativeAdListener)
                        .build());
    }
}

我们稍后再返回,并在 onAdLoaded() 方法中添加代码。

第 2 步:创建原生横幅广告布局

接下来,提取广告元数据,并使用广告属性创建自定义原生 UI。您可以在布局 .xml 中创建自定义视图,或在代码中添加元素。

请参阅原生广告准则,了解如何在您的应用中设计原生横幅广告。

在您的 Activity 布局 activity_main.xml 中,为原生横幅广告添加容器。该容器应为 com.facebook.ads.NativeAdLayou,它是 FrameLayout 顶部的一个封装程序,且具备一些额外功能,使我们能够在广告上方呈现原生广告报告流程。然后,在 onAdLoaded() 方法中,您需要将您的原生广告视图填充至此容器中。

<?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">
    ...
    <com.facebook.ads.NativeAdLayout
        android:id="@+id/native_banner_ad_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true" />
    ...
</RelativeLayout>

为原生横幅广告创建自定义布局 native_banner_ad_unit.xml



下方为原生横幅广告的自定义布局示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="horizontal">

        <RelativeLayout
            android:id="@+id/ad_choices_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="2dp" />

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

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/white">

        <com.facebook.ads.MediaView
            android:id="@+id/native_icon_view"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:gravity="center" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:orientation="vertical"
            android:paddingLeft="53dp"
            android:paddingRight="83dp">

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

            <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:textSize="12sp" />
        </LinearLayout>

        <Button
            android:id="@+id/native_ad_call_to_action"
            android:layout_width="80dp"
            android:layout_height="50dp"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:background="#4286F4"
            android:gravity="center"
            android:paddingLeft="3dp"
            android:paddingRight="3dp"
            android:textColor="@android:color/white"
            android:textSize="12sp"
            android:visibility="gone" />

    </RelativeLayout>
</LinearLayout>

第 3 步:使用广告元数据填充布局

情景 1:在广告成功加载后立即显示。修改上述 onAdLoaded() 方法,以检索 Native Banner Ad's 属性,并以下列方式显示广告:

public class NativeBannerAdActivity extends Activity {

    private NativeAdLayout nativeAdLayout;
    private LinearLayout adView;
    private NativeBannerAd nativeBannerAd;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Instantiate a NativeBannerAd 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).
        nativeBannerAd = new NativeBannerAd(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 (nativeBannerAd == null || nativeBannerAd != ad) {
                    return;
                 }
                // Inflate Native Banner Ad into Container
                inflateAd(nativeBannerAd);
            }
            ...
        });
        // load the ad
        nativeBannerAd.loadAd(
                nativeBannerAd.buildLoadAdConfig()
                        .withAdListener(nativeAdListener)
                        .build());
    }

    private void inflateAd(NativeBannerAd nativeBannerAd) {
        // Unregister last ad
        nativeBannerAd.unregisterView();

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

        // Add the AdChoices icon
        RelativeLayout adChoicesContainer = adView.findViewById(R.id.ad_choices_container);
        AdOptionsView adOptionsView = new AdOptionsView(NativeBannerAdActivity.this, nativeBannerAd, nativeAdLayout);
        adChoicesContainer.removeAllViews();
        adChoicesContainer.addView(adOptionsView, 0);

        // Create native UI using the ad metadata.
        TextView nativeAdTitle = adView.findViewById(R.id.native_ad_title);
        TextView nativeAdSocialContext = adView.findViewById(R.id.native_ad_social_context);
        TextView sponsoredLabel = adView.findViewById(R.id.native_ad_sponsored_label);
        MediaView nativeAdIconView = adView.findViewById(R.id.native_icon_view);
        Button nativeAdCallToAction = adView.findViewById(R.id.native_ad_call_to_action);

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

        // Register the Title and CTA button to listen for clicks.
        List<View> clickableViews = new ArrayList<>();
        clickableViews.add(nativeAdTitle);
        clickableViews.add(nativeAdCallToAction);
        nativeBannerAd.registerViewForInteraction(adView, nativeAdIconView, clickableViews);
    }
}

SDK 将自动记录广告展示并处理点击。请注意,您必须利用 NativeBannerAd 实例注册广告视图才能启用此功能。如要让所有广告元素都可以点击,请使用下列代码注册此视图:

registerViewForInteraction(View view, MediaView adIconView)

情景 2:在广告成功加载几秒或几分钟后显示。显示广告前,您应检查广告是否已经无效。

如果广告在加载后没有立即显示,开发者需负责检查广告是否已经无效。成功加载后,广告的有效期为 60 分钟。如果您展示无效广告,则将无法收款。您应调用 isAdInvalidated() 来验证广告。

您应该遵循下列思路,但请不要把代码复制到自己的项目中,因为这只是一个示例:

public class NativeBannerAdActivity extends Activity {

    private NativeBannerAd nativeBannerAd;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Instantiate a NativeBannerAd 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).
        nativeBannerAd = new NativeBannerAd(this, "YOUR_PLACEMENT_ID");
         NativeAdListener nativeAdListener = new NativeAdListener() {
            ...
        });
        // load the ad
        nativeBannerAd.loadAd(
                nativeBannerAd.buildLoadAdConfig()
                        .withAdListener(nativeAdListener)
                        .build());
    }

    private void showAdWithDelay() {
       /**
        * 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 nativeBannerAd has been loaded successfully
               if(nativeBannerAd == null || !nativeBannerAd.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(nativeBannerAd.isAdInvalidated()) {
                   return;
               }
               inflateAd(nativeBannerAd); // Inflate Native Banner Ad into Container same as in previous code example
           }
       }, 1000 * 60 * 15); // Show the ad after 15 minutes
    }
}

控制可点击的区域

为打造更优质的用户体验,并获得更理想的成效,建议您始终考虑控制可点击的广告区域,避免无意点击。请参阅 Audience Network SDK 政策页面,详细了解有关空白区域不可点击的规定。

为了更好地控制可点击的内容,您可以使用 registerViewForInteraction(View view, MediaView adIconView, List<View> clickableViews) 注册可点击视图的列表。举例来说,如果您只希望前面示例中的广告标题和行动号召按钮可以点击,则可编写如下代码:

@Override
public void onAdLoaded(Ad ad) {
  ...
  List<View> clickableViews = new ArrayList<>();
  clickableViews.add(nativeAdTitle);
  clickableViews.add(nativeAdCallToAction);
  nativeBannerAd.registerViewForInteraction(mAdView, nativeAdIconView, clickableViews);
  ...
}

如果需要在一定时间以后重复使用相同的视图来显示不同广告,请确保在使用不同的 NativeBannerAd 实例注册相同视图之前调用 unregisterView()

运行代码,即可显示原生横幅广告:

加载广告后,下列属性将包含一些值:titleiconcallToAction。其他属性则可能为 null 值或空值。请确保您的代码足够强大,能够处理这些情况。


无广告展示时,系统将调用 onError,其中会设置 error.code。如果您使用自己的自定义报告或中介层级,则可能需要检查代码值并检测这一情况。在这种情况下,您可回退至另一个广告网络,但请勿立即重新请求广告。


您可以缓存接收的广告元数据,并重复利用长达 30 分钟。如果您计划在这段时间过后再使用元数据,请通过调用来加载新广告。

后续步骤

  • 查看原生广告模板指南,以在您的应用中添加广告。

  • 请查看我们的代码示例,了解如何使用原生广告。NativeBannerAdSample 现已作为 SDK 的组成部分,可在 AudienceNetwork/samples 文件夹中找到。将项目导入您的 IDE,然后在设备或模拟器上运行。

更多资源

入门指南

Audience Network 入门技术指南

代码示例

Audience Network 广告集成示例

常见问题

Audience Network 常见问题

原生广告模板

更简便的原生广告集成方法