原生高级广告(统一)

原生高级广告是一种广告格式,这种广告中的素材资源通过平台原本就有的界面组件展示给用户。这种广告使用您在构建布局时已经采用的同类视图进行展示,而且能以和周围视觉设计相称的形式呈现,让用户有浑然一体的使用体验。从代码编写的角度来说,这意味着当原生广告加载时,您的应用会收到一个包含其素材资源的 NativeAd 对象,然后就由此应用(而不是 SDK)负责展示它们了。

系统定义的原生广告格式有两种:应用安装广告和内容广告。 这两种广告均由 UnifiedNativeAd 表示。此类的实例包含原生广告的素材资源。请注意,根据 UnifiedNativeAd 表示的广告类型,某些字段中不会填充任何值(即为 nil)。 本指南介绍了如何将原生高级广告植入到 Android 应用中。

前提条件

加载广告

原生广告通过 AdLoader 类加载,该类有自己的 Builder 类,用于在创建过程中进行自定义。应用在构建 AdLoader 的过程中会向其添加监听器,以此方式指定它准备接收哪些类型的原生广告。这样,AdLoader 就会只请求这些类型的广告。

构建 AdLoader

以下代码演示了如何构建可加载统一原生广告的 AdLoader

Java

AdLoader adLoader = new AdLoader.Builder(context, "ca-app-pub-3940256099942544/2247696110")
    .forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
        @Override
        public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
            // Show the ad.
        }
    })
    .withAdListener(new AdListener() {
        @Override
        public void onAdFailedToLoad(int errorCode) {
            // Handle the failure by logging, altering the UI, and so on.
        }
    })
    .withNativeAdOptions(new NativeAdOptions.Builder()
            // Methods in the NativeAdOptions.Builder class can be
            // used here to specify individual options settings.
            .build())
    .build();

Kotlin

val adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110")
        .forUnifiedNativeAd { ad : UnifiedNativeAd ->
            // Show the ad.
        }
        .withAdListener(object : AdListener() {
            override fun onAdFailedToLoad(errorCode: Int) {
                // Handle the failure by logging, altering the UI, and so on.
            }
        })
        .withNativeAdOptions(NativeAdOptions.Builder()
                // Methods in the NativeAdOptions.Builder class can be
                // used here to specify individual options settings.
                .build())
        .build()

为 UnifiedNativeAd 格式做准备

上例中首先调用的方法负责为 UnifiedNativeAd 格式准备 AdLoader

forUnifiedNativeAd()
调用此方法会将 AdLoader 配置为请求统一原生广告。当广告成功加载后,会调用监听器对象的 onUnifiedNativeAdLoaded() 方法。

AdLoader 发出广告请求后,Google 会选择能使发布商收益最大化的广告,然后将该广告返回。

将 AdListener 与 AdLoader 配合使用

在创建上述 AdLoader 的过程中,withAdListener 函数会设置一个 AdListener

这是一个可选步骤。该方法将 AdListener 作为其唯一参数,当广告生命周期事件发生时,此参数会收到来自 AdLoader 的回调:

Java

.withAdListener(new AdListener() {
    // AdListener callbacks like OnAdFailedToLoad, OnAdOpened, OnAdClicked and
    // so on, can be overridden here.
})

Kotlin

.withAdListener(object : AdListener() {
    // AdListener callbacks like OnAdFailedToLoad, OnAdOpened, OnAdClicked and
    // so on, can be overridden here.
})

AdListeners 处理原生广告的方式与处理横幅广告和插页式广告的方式有一项重要区别。由于 AdLoader 自己就有因具体格式而异的监听器(即 UnifiedNativeAd.OnUnifiedNativeAdLoadedListener)可在广告加载时使用,因此当原生广告成功加载时,并不会调用 AdListener 中的 onAdLoaded() 方法

设置选项

withNativeAdOptions()

上述 AdLoader 的创建过程中包含的最后一个函数是另一个可选方法 withNativeAdOptions()

Java

.withNativeAdOptions(new NativeAdOptions.Builder()
    // Methods in the NativeAdOptions.Builder class can be
    // used here to specify individual options settings.
    .build()
)

Kotlin

.withNativeAdOptions(NativeAdOptions.Builder()
    // Methods in the NativeAdOptions.Builder class can be
    // used here to specify individual options settings.
    .build()
)

通过 NativeAdOptions 对象,应用可以设置在发出请求时使用的具体选项。该对象的 Builder 类提供了可以在创建实例时使用的以下方法:

setReturnUrlsForImageAssets()

原生广告的图片素材资源是通过 NativeAd.Image 实例返回的,该类中包含一个 Drawable 和一个 Uri。如果此选项设置为 false(这是默认值),则 SDK 会自动获取图片素材资源,并为您填充 DrawableUri。不过,如果设置为 true,SDK 会仅填充 Uri 字段,从而允许您自行决定是否下载实际图片。

setImageOrientation()

某些广告素材有多张可用图片,分别适用于不同的设备屏幕方向。使用 NativeAdOptions 屏幕方向常量(ORIENTATION_PORTRAITORIENTATION_LANDSCAPEORIENTATION_ANY)之一调用此方法,可请求适用于特定屏幕方向的图片。如果未调用此方法,则会使用默认值 ORIENTATION_LANDSCAPE

setRequestMultipleImages()

某些图片素材资源包含的是一系列图片,而不只是一张图片。如果您的应用将此值设置为 true,则表示它已做好准备,可以为任何包含多张图片的素材资源展示所有图片。如果您的应用将此值设置为 false(默认),则说明它指示 SDK 为包含一系列图片的任何素材资源仅提供第一张图片。

如果在创建 AdLoader 时根本未调用 withNativeAdOptions,则会使用每个选项的默认值。

setAdChoicesPlacement()

默认情况下,广告选择叠加层会显示在右上角。应用可以通过将此属性设置为以下其中一项来更改此叠加层的呈现位置:

  • ADCHOICES_TOP_LEFT
  • ADCHOICES_TOP_RIGHT
  • ADCHOICES_BOTTOM_RIGHT
  • ADCHOICES_BOTTOM_LEFT
setVideoOptions()

应用可以使用此方法为作为原生广告一部分返回的视频素材资源设置选项。有关更多信息,请参阅本指南后面的原生视频广告部分。

加载广告

构建完 AdLoader 后,就可以使用它来加载广告了。加载广告有 loadAd()loadAds() 两种方法。

注意:loadAds() 方法目前仅适用于 AdMob 广告。对于参与中介的广告,请改为使用 loadAd()

loadAd() 方法为单个广告发送请求:

loadAd()
此方法为单个广告发送请求。

Java

adLoader.loadAd(new AdRequest.Builder().build());

Kotlin

adLoader.loadAd(AdRequest.Builder().build())
loadAds()
此方法为多个广告(最多 5 个)发送请求。

Java

adLoader.loadAds(new AdRequest.Builder().build(), 3);

Kotlin

adLoader.loadAds(AdRequest.Builder().build(), 3)

这两个方法都将AdRequest对象作为第一个参数。这与横幅广告和插页式广告使用的AdRequest类相同,并且您可以使用AdRequest类的方法来添加定位信息,就像处理其他广告格式一样。

loadAds() 还需要另外一个参数,即 SDK 应尝试为该请求加载的广告数量。此数值最大为 5,而且无法保证 SDK 返回的广告数量一定等于所请求的广告数量。如果调用 loadAds() 后返回了多个广告,则这些广告将互不相同。

调用 loadAd() 后,将对上面定义的监听器方法进行一次回调,以投放原生广告对象或报告错误。

调用 loadAds() 后,将进行多次此类回调(至少一次,但不超过请求的广告数量)。请求多个广告的应用应在其回调实现代码中调用 AdLoader.isLoading(),以确定是否已完成加载过程。

下例显示了如何在 onUnifiedNativeAdLoaded() 回调中检查 isLoading()

Java

final AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110")
        .forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
    @Override
    public void onUnifiedNativeAdLoaded(UnifiedNativeAd ad) {
        ...
        // some code that displays the ad.
        ...
        if (adLoader.isLoading()) {
            // The AdLoader is still loading ads.
            // Expect more adLoaded or onAdFailedToLoad callbacks.
        } else {
            // The AdLoader has finished loading ads.
        }
    }
}).build();

adLoader.loadAds(new AdRequest.Builder().build(), 3);

Kotlin

lateinit var adLoader: AdLoader
...
adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110")
    .forUnifiedNativeAd {
        ...
        // some code that displays the ad.
        ...

        if (adLoader.isLoading) {
            // The AdLoader is still loading ads.
            // Expect more adLoaded or onAdFailedToLoad callbacks.
        } else {
            // The AdLoader has finished loading ads.
        }
    }.build()

adLoader.loadAds(AdRequest.Builder().build(), 3)

务必用测试广告进行测试

在开发和测试应用时,请确保使用的是测试广告,而不是实际投放的广告。否则,可能会导致您的帐号被暂停。

对于在 Android 上投放的原生高级广告,加载测试广告最简便的方法就是使用下面的专用测试广告单元 ID:

ca-app-pub-3940256099942544/2247696110

该测试广告单元 ID 已经过专门配置,可以为每个请求返回测试广告,您可以在自己应用的编码、测试和调试过程中随意使用该测试广告单元 ID。只需确保您会在发布应用前用自己的广告单元 ID 替换该测试广告单元 ID 即可。

如需详细了解移动广告 SDK 的测试广告如何运作,请参阅测试广告

何时请求广告

展示原生广告的应用可以在实际展示之前请求这些广告。在许多情况下,这是推荐的做法。例如,如果某款应用展示一个商品清单,其中会夹杂一些原生广告,那么该应用就可以加载整个清单中的原生广告,因为它知道一些广告仅在用户滚动浏览视图后才会展示,还有一些可能根本不会展示。

展示广告

加载原生广告时,SDK 会调用相应广告格式的监听器。然后,就由您的应用负责展示广告了,尽管不一定要立即展示广告。为了更轻松地展示系统定义的广告格式,SDK 提供了一些有用的资源,如下所述。

UnifiedNativeAdView

对于 UnifiedNativeAd 格式,有相应的 UnifiedNativeAdView 类。此类是一个 ViewGroup,发布商应将其用作 UnifiedNativeAd 的根。一个 UnifiedNativeAdView 对应于一个统一原生广告。凡是用于展示该广告素材资源的每个视图(例如,展示屏幕截图素材资源的 ImageView),均应是 UnifiedNativeAdView 对象的子对象。

对于使用 LinearLayout 来展示素材资源视图的统一原生广告,其视图层次结构可能如下所示:

<com.google.android.gms.ads.formats.UnifiedNativeAdView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <LinearLayout
    android:orientation="vertical"
    ... >
        <LinearLayout
        android:orientation="horizontal"
        ... >
          <ImageView
           android:id="@+id/ad_app_icon"
           ... />
          <TextView
            android:id="@+id/ad_headline"
            ... />
         </LinearLayout>

         // Other assets such as image or media view, call to action, etc follow.
         ...
    </LinearLayout>
</com.google.android.gms.ads.formats.UnifiedNativeAdView>

下面这个示例代码段创建了一个 UnifiedNativeAdView,然后用 UnifiedNativeAd 填充该视图:

Java

AdLoader.Builder builder = new AdLoader.Builder(this, "<your ad unit ID>")
    .forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
        @Override
        public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
            // Assumes you have a placeholder FrameLayout in your View layout
            // (with id fl_adplaceholder) where the ad is to be placed.
            FrameLayout frameLayout =
                findViewById(R.id.fl_adplaceholder);
            // Assumes that your ad layout is in a file call ad_unified.xml
            // in the res/layout folder
            UnifiedNativeAdView adView = (UnifiedNativeAdView) getLayoutInflater()
                .inflate(R.layout.ad_unified, null);
            // This method sets the text, images and the native ad, etc into the ad
            // view.
            populateUnifiedNativeAdView(unifiedNativeAd, adView);
            frameLayout.removeAllViews();
            frameLayout.addView(adView);
        }
});

Kotlin

val builder = AdLoader.Builder(this, "<your ad unit ID>")
    .forUnifiedNativeAd { unifiedNativeAd ->
        // Assumes that your ad layout is in a file call ad_unified.xml
        // in the res/layout folder
        val adView = layoutInflater
                .inflate(R.layout.ad_unified, null) as UnifiedNativeAdView
        // This method sets the text, images and the native ad, etc into the ad
        // view.
        populateUnifiedNativeAdView(unifiedNativeAd, adView)
        // Assumes you have a placeholder FrameLayout in your View layout
        // (with id ad_frame) where the ad is to be placed.
        ad_frame.removeAllViews()
        ad_frame.addView(adView)
    }

广告视图类还提供了每项素材资源所用视图的注册方法,并提供了一个用于注册 NativeAd 对象本身的方法。如果以这种方式注册视图,SDK 就可以自动处理诸如以下任务:

  • 记录点击次数
  • 记录展示次数(当第一个像素出现在屏幕上时)
  • 显示广告选择叠加层

广告选择叠加层

SDK 会向每个广告视图中添加一个广告选择叠加层。请在原生广告视图中任选您喜欢的一角留出空间,用于展示自动插入的广告选择徽标。此外,广告选择叠加层一定要显眼易见,因此请选择适当的背景颜色和图片。如需详细了解此叠加层的外观和功能,请参阅原生高级广告字段说明

广告标示

您必须展示广告标示,以指明该视图是广告。 请参阅此页了解政策指南

代码示例

以下是展示统一原生广告的步骤:

  1. 创建 UnifiedNativeAdView 类的实例。
  2. 对于要展示的每个广告素材资源:
    1. 使用广告对象中的素材资源填充素材资源视图。
    2. ViewGroup 类注册该素材资源视图。
  3. 如果您的原生广告布局包含大型媒体素材资源,请注册 MediaView
  4. ViewGroup 类注册广告对象。

以下是一个展示 UnifiedNativeAd 的示例函数:

Java

private void displayUnifiedNativeAd(ViewGroup parent, UnifiedNativeAd ad) {

    // Inflate a layout and add it to the parent ViewGroup.
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    UnifiedNativeAdView adView = (UnifiedNativeAdView) inflater
            .inflate(R.layout.my_ad_layout, parent);

    // Locate the view that will hold the headline, set its text, and call the
    // UnifiedNativeAdView's setHeadlineView method to register it.
    TextView headlineView = adView.findViewById<TextView>(R.id.ad_headline);
    headlineView.setText(ad.getHeadline());
    adView.setHeadlineView(headlineView);

    ...
    // Repeat the above process for the other assets in the UnifiedNativeAd
    // using additional view objects (Buttons, ImageViews, etc).
    ...

    // If the app is using a MediaView, it should be
    // instantiated and passed to setMediaView. This view is a little different
    // in that the asset is populated automatically, so there's one less step.
    MediaView mediaView = (MediaView) adView.findViewById(R.id.ad_media);
    adView.setMediaView(mediaView);

    // Call the UnifiedNativeAdView's setNativeAd method to register the
    // NativeAdObject.
    adView.setNativeAd(ad);

    // Ensure that the parent view doesn't already contain an ad view.
    parent.removeAllViews();

    // Place the AdView into the parent.
    parent.addView(adView);
}

Kotlin

fun displayUnifiedNativeAd(parent: ViewGroup, ad: UnifiedNativeAd) {

    // Inflate a layout and add it to the parent ViewGroup.
    val inflater = parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)
            as LayoutInflater
    val adView = inflater.inflate(R.layout.my_ad_layout, parent) as UnifiedNativeAdView

    // Locate the view that will hold the headline, set its text, and use the
    // UnifiedNativeAdView's headlineView property to register it.
    val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
    headlineView.text = ad.headline
    adView.headlineView = headlineView

    ...
    // Repeat the above process for the other assets in the UnifiedNativeAd using
    // additional view objects (Buttons, ImageViews, etc).
    ...

    // If the app is using a MediaView, it should be instantiated and assigned
    // to the mediaView property. This view is a little different in that the asset
    // is populated automatically, so there's one less step.
    val mediaView = adView.findViewById<MediaView>(R.id.ad_media)
    adView.mediaView = mediaView

    // Call the UnifiedNativeAdView's setNativeAd method to register the
    // NativeAdObject.
    adView.setNativeAd(ad)

    // Ensure that the parent view doesn't already contain an ad view.
    parent.removeAllViews()

    // Place the AdView into the parent.
    parent.addView(adView)
}

让我们来看看各项具体任务:

填充布局

Java

LayoutInflater inflater = (LayoutInflater) parent.getContext()
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
UnifiedNativeAdView adView = (UnifiedNativeAdView) inflater
        .inflate(R.layout.my_ad_layout, parent);

Kotlin

val inflater = parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)
        as LayoutInflater
val adView = inflater.inflate(R.layout.my_ad_layout, parent) as UnifiedNativeAdView

在本示例中,我们要填充一个 XML 布局(该布局包含用于展示统一原生广告的视图),然后找到对 UnifiedNativeAdView 的引用。请注意,如果您的片段或活动中有现成的 UnifiedNativeAdView,也可以加以重用;您甚至可以在不使用布局文件的情况下动态创建一个实例。

填充和注册素材资源视图

下面的示例代码会找到用于显示标题的视图,使用由广告对象提供的字符串素材资源设置其文字,然后使用向 UnifiedNativeAdView 对象注册该视图:

Java

TextView headlineView = adView.findViewById<TextView>(R.id.ad_headline);
headlineView.setText(ad.getHeadline());
adView.setHeadlineView(headlineView);

Kotlin

val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
headlineView.text = ad.headline
adView.headlineView = headlineView

对于应用要展示的由原生广告对象提供的每项素材资源,都应为其重复上述过程,即找到相应视图、设置其值并向广告视图类注册它。

点击处理

以下是一个使用广告监听器观察点击事件的示例代码段:

Java

.withAdListener(new AdListener() {
    @Override onAdClicked() {
      // Log the click event or other custom behavior.
    }
})

Kotlin

.withAdListener(object : AdListener() {
    override fun onAdClicked() {
      // Log the click event or other custom behavior.
    }
})

注册 MediaView

MediaView 是一个专门用于展示主媒体素材资源的 View。它具有以下行为:

  • 如果加载的广告具有视频素材资源,则会对视频进行缓冲并开始在 MediaView 内播放。
  • 如果加载的广告不包含视频素材资源,则会改为下载第一个图片素材资源并将其放置在 MediaView 内。

MediaView 是一个可以在 XML 布局中定义或动态构建的 View。就像所有其他素材资源视图一样,应该将其放在 NativeAdView 的视图层次结构中。对于使用 MediaView 的应用,不需要在其中填充素材资源,但必须向 NativeAdView 注册它,如下所示:

Java

MediaView mediaView = adView.findViewById(R.id.ad_media);
adView.setMediaView(mediaView);

Kotlin

adView.mediaView = adView.findViewById(R.id.ad_media)

注册原生广告对象

这是最后一步,也就是向负责显示原生广告对象的视图注册该对象:

Java

adView.setNativeAd(ad);

Kotlin

adView.setNativeAd(ad)

原生视频广告

除了图片、文字和数字外,有些原生广告会包含视频素材资源。但不是每个广告都会包含视频素材资源,也不需要相关应用展示这些资源。

为了简化视频的配置和展示,移动广告 SDK 提供了与视频相关的以下类:

VideoOptions

VideoOptions 类供应用用来配置原生视频素材资源的行为方式。 VideoOptions 对象应该分配给构建 AdLoader 时使用的 NativeAdOptions 对象:

Java

VideoOptions videoOptions = new VideoOptions.Builder()
        .setStartMuted(false)
        .build();

NativeAdOptions adOptions = new NativeAdOptions.Builder()
        .setVideoOptions(videoOptions)
        .build();

AdLoader adLoader = new AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110")
        .forUnifiedNativeAd( ... )
        .withNativeAdOptions(adOptions)
        .build();

Kotlin

val videoOptions = VideoOptions.Builder()
        .setStartMuted(false)
        .build()

val adOptions = NativeAdOptions.Builder()
        .setVideoOptions(videoOptions)
        .build()

val adLoader = AdLoader.Builder(this, "ca-app-pub-3940256099942544/2247696110")
        .forUnifiedNativeAd( ... )
        .withNativeAdOptions(adOptions)
        .build()

VideoOptions.Builder 类目前提供了 setStartMuted() 这一方法,该方法用于指示 SDK 是否应该在静音状态下开始播放视频素材资源。其默认值为 true

VideoController

VideoController 类用于获取有关视频素材资源的信息。 应用可以通过调用 getVideoController() 方法从 UnifiedNativeAd 获得对该控制器的引用:

Java

VideoController vc = myNativeAd.getVideoController();

Kotlin

val vc = myNativeAd.videoController

即使广告中没有视频素材资源,此方法也会始终返回 VideoController 对象。

VideoController 提供以下视频状态查询方法:

  • hasVideoContent() - 如果广告中有视频素材资源,则此方法返回 true,否则返回 false。
  • getAspectRatio() - 此方法返回视频的宽高比(宽度除以高度),如果没有视频素材资源,则返回零。

应用也可以使用 VideoController.VideoLifecycleCallbacks 类,以便在视频素材资源生命周期内发生事件时收到通知:

Java

VideoController vc = nativeAd.getVideoController();

vc.setVideoLifecycleCallbacks(new VideoController.VideoLifecycleCallbacks() {
    public void onVideoEnd() {
        // Here apps can take action knowing video playback is finished.
        // It's always a good idea to wait for playback to complete before
        // replacing or refreshing a native ad, for example.
        super.onVideoEnd();
    }
});

Kotlin

val vc = nativeAd.videoController

vc.setVideoLifecycleCallbacks(object : VideoController.VideoLifecycleCallbacks() {
    override fun onVideoEnd() {
        // Here apps can take action knowing video playback is finished.
        // It's always a good idea to wait for playback to complete before
        // replacing or refreshing a native ad, for example.
        super.onVideoEnd()
    }
})

销毁广告

当完成原生广告展示后,您应该将其销毁,以便系统正确地对广告进行垃圾回收处理。

Java

nativeAd.destroy();

Kotlin

nativeAd.destroy()

其他资源

GitHub 上的示例

Codelab

后续步骤

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面