原生广告 - 自定义呈现

此功能目前仅在有限范围内进行测试。如果您有兴趣参与测试,请与您的客户经理联系,讨论是否可行。此功能将在测试结束后提供给所有发布商。

有关实现原生广告自定义呈现的端到端演示,请参见代码实验室

本指南将向您介绍如何使用 Google 移动广告 SDK 在 Android 应用中实现 DFP 原生广告以及一些需要考虑的重要事项。

前提条件

本指南假定您已经掌握了一些 Google 移动广告 SDK 的应用知识。如果没有的话,不妨先通读我们的入门指南

什么是原生广告?

原生广告是通过平台自身的界面组件向用户呈现的广告。它们在展示时使用的广告视图类型与您已用于构建布局的类型相同,并且可以设置格式,以与它们所在的用户体验视觉设计相符。以编码术语来说,这意味着在加载原生广告时,您的应用将收到一个包含其素材资源的 NativeAd 对象,然后由应用(而不是 SDK)负责展示它们。

系统定义的原生广告格式

有两种系统定义的原生广告格式:应用安装广告和内容广告。应用安装广告由 NativeAppInstallAd 表示,内容广告由 NativeContentAd 表示。这些对象包含原生广告的素材资源。

自定义原生广告格式

除了系统定义的原生广告格式,DFP 广告管理系统(以下简称 DFP)发布商还可以通过定义素材资源的自定义列表来生成自己的原生广告格式。这些称为自定义原生广告格式,可以用于预留广告。这样,发布商就可以将任意结构化数据传递到其应用。这些广告由 NativeCustomTemplateAd 对象表示。

加载系统定义的广告格式

原生广告通过 AdLoader 类加载,后者有自己的 Builder 类,可在创建过程中实现自定义。通过在构建过程中将监听器添加到 AdLoader,应用会指定它准备接受哪些类型的原生广告。然后,AdLoader 将仅请求这些类型。

构建 AdLoader

以下代码演示了如何构建可在单个请求中加载应用安装广告或内容广告的 AdLoader

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forAppInstallAd(new OnAppInstallAdLoadedListener() {
        @Override
        public void onAppInstallAdLoaded(NativeAppInstallAd appInstallAd) {
            // Show the app install ad.
        }
    })
    .forContentAd(new OnContentAdLoadedListener() {
        @Override
        public void onContentAdLoaded(NativeContentAd contentAd) {
            // Show the content ad.
        }
    })
    .withAdListener(new AdListener() {
        @Override
        public void onAdFailedToLoad(int errorCode) {
            // Handle the failure by logging, altering the UI, etc.
        }
    })
    .withNativeAdOptions(new NativeAdOptions.Builder()
            // Methods in the NativeAdOptions.Builder class can be
            // used here to specify individual options settings.
            .build())
    .build();

为各种格式做准备

上例中首先调用的两种方法负责为特定类型的原生广告准备 AdLoader

forAppInstallAd - 调用此方法会配置 AdLoader 以请求应用安装广告。当成功加载后,将调用监听器对象的 onAppInstallAdLoaded 方法。

forContentAd - 此方法的工作原理与 forAppInstallAd 一样,但用于请求内容广告。当成功加载后,将在监听器对象上调用 onContentAdLoaded 方法。

即使广告加载程序有多个原生广告格式的处理程序,SDK 也只会生成一个广告请求。Google 将选择并返回能使发布商收益最大化的广告。

将 AdListener 与 AdLoader 配合使用

创建上述 AdLoader 的过程中还包括设置 AdListener 的函数:withAdListener。这是一个可选步骤。该方法将 AdListener 作为其孤立参数,当广告生命周期事件发生时,它将接收来自 AdLoader 的回调:

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

AdListeners 处理原生广告的方式与处理横幅和插页式广告的方式之间有一个重要区别。由于 AdLoader 有自己的特定于格式的监听器(OnAppInstallAdLoadedListener 等)可在广告加载时使用,因此在成功加载原生广告时不会调用 AdListener 中的 onAdLoaded 方法

NativeAdOptions

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

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

NativeAdOptions 对象允许应用设置用于发出请求的特定选项。它的 Builder 类提供了在创建实例时使用的这些方法:

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

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

如果使用 setImageOrientation 指定横向或纵向图片方向首选项,SDK 将首先在图片资源数组中放置与该方向匹配的图片,然后将不匹配的图片放在它们后面。由于某些广告只能有一个方向,发布商应确保其应用可同时处理横向和纵向图片。

setRequestMultipleImages - 某些图片资源会包含一系列图片,而不只是一个。将此值设置为 true,则您的应用指示它已准备好展示任何包含多个图片的素材资源的所有图片。将其设置为 false(默认),您的应用会指示 SDK 仅提供任何包含一系列图片的素材资源中的第一张图片。

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

setAdChoicesPlacement()

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

  • ADCHOICES_TOP_LEFT
  • ADCHOICES_TOP_RIGHT
  • ADCHOICES_BOTTOM_RIGHT
  • ADCHOICES_BOTTOM_LEFT

加载原生广告

完成 AdLoader 的构建之后,调用其 loadAd 方法请求广告:

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

请注意,AdLoaders 使用与横幅广告和插页式广告相同的 PublisherAdRequest 类。您可以使用该类的方法来添加定位信息,就像处理其他广告类型一样。

单个 AdLoader 可以发出多个请求,但一次只能完成一个请求。重复使用 AdLoader 时,请确保等待每个请求完成,然后再次调用 loadAd 以开始下一个请求。如果您需要并行请求多个广告,则可以使用多个 AdLoader 对象。

何时请求广告

展示原生广告的应用可以在实际展示之前请求这些广告。在许多情况下,这是推荐的做法。例如,如果应用展示其中包含原生广告的项目列表,则可以针对整个列表加载原生广告,并且知道一些广告将仅在用户滚动视图之后展示,而一些可能根本不会展示。

预提取广告是一项便利的技术,但发布商要注意不要永远保留旧广告,而不进行展示。对任何原生广告对象来说,如果在保留一小时后仍没有获得展示,就应该被舍弃,并替换为来自新请求的新广告。

展示系统定义的广告格式

加载原生广告时,SDK 会调用相应广告格式的监听器。然后,由您的应用负责展示广告,但不一定要立即执行。为了方便展示系统定义的广告格式,SDK 提供了一些有用的资源。

广告视图类

对于每种系统定义的格式,都有一个相应的广告视图类:应用安装广告为 NativeAppInstallAdView,内容广告为 NativeContentAdView。这些广告视图类是 ViewGroups,发布商应将其用作相应格式的原生广告的根。例如,单个 NativeContentAdView 对应于单个内容广告。用于展示该广告素材资源的每个视图(例如,展示屏幕截图素材资源的 ImageView)都应为 NativeContentAdView 对象的子对象。

以下示例说明了使用 RelativeLayout 展示其素材资源视图的内容广告的视图层次结构:

广告视图类还提供了用于注册每个单独的素材资源所用视图的方法以及一个用于注册 NativeAd 对象本身的方法。以这种方式注册视图允许 SDK 自动处理以下任务:

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

广告选择叠加层

当返回补余广告时,SDK 会向广告视图添加广告选择叠加层。如果您的应用使用原生补余广告,请在原生广告视图您偏好的角中留出空间,以便自动插入广告选择徽标。此外,广告选择叠加层一定要显眼易见,因此请选择适当的背景颜色和图片。有关叠加层外观和功能的详细信息,请参阅原生补余广告实现指南

代码示例

以下是展示系统定义的原生广告格式的步骤:

  1. 创建正确的广告视图类的实例。
  2. 对于要展示的每个广告素材资源:
    1. 使用原生广告对象中的素材资源填充素材资源视图。
    2. 使用 ViewGroup 类注册素材资源视图。
  3. 使用 ViewGroup 类注册原生广告对象。

这是一个展示 NativeContentAd 的示例函数:

private void displayContentAd(ViewGroup parent, NativeContentAd contentAd) {
    // Inflate a layout and add it to the parent ViewGroup.
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    NativeContentAdView adView = (NativeContentAdView) inflater
            .inflate(R.layout.my_content_ad, parent);

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

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

    // Call the NativeContentAdView's setNativeAd method to register the
    // NativeAdObject.
    adView.setNativeAd(contentAd);

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

让我们来看看各个任务:

放大布局

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

在本示例中,我们将放大一个 XML 布局,该布局中包含用于展示内容广告的视图,然后找到对作为其根元素的 NativeContentAdView 的引用。这是一种很好的入门方式,但请注意,如果您的片段或活动中有现成的 NativeContentAdView,您也可以重用它,甚至能在不使用布局文件的情况下动态创建实例。

填充和注册素材资源视图

TextView headlineView = (TextView) adView.findViewById(R.id.contentad_headline);
headlineView.setText(contentAd.getHeadline());
adView.setHeadlineView(headlineView);

这里我们要定位将用于显示标题的视图,使用由 contentAd 提供的字符串素材资源设置其文字,然后使用 NativeContentAdView 对象注册。应该为由原生广告对象提供的每个素材资源重复定位此视图、设置其值并使用广告视图类进行注册的过程。

注册原生广告对象

adView.setNativeAd(contentAd);

最后一步将原生广告对象注册到负责显示原生广告对象的视图。

加载自定义原生广告格式

构建 AdLoader

与系统定义的原生广告格式类似,自定义原生广告格式也是使用 AdLoader 类加载:

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomTemplateAd("10063170",
      new NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener() {
          @Override
          public void onCustomTemplateAdLoaded(NativeCustomTemplateAd ad) {
              // Show the custom template and record an impression.
          }
      },
      new NativeCustomTemplateAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomTemplateAd ad, String s) {
              // Handle the click action
          }
      })
    .withAdListener( ... )
    .withNativeAdOptions( ... )
    .build();

forAppInstallAd 方法配置 AdLoader 来请求应用安装广告非常类似,forCustomTemplateAd 方法对 AdLoader 进行设置,以处理自定义模板广告。有三个参数传递到该方法中:

  • AdLoader 应该请求的自定义模板的模板 ID。每个自定义原生广告格式都具有与其相关联的模板 ID 值。此参数指示您的应用希望 AdLoader 请求哪个模板。
  • 广告成功加载后要调用的 OnCustomTemplateAdLoadedListener
  • 用户点按或点击广告时调用的可选 OnCustomClickListener。有关此监听器的详情,请参阅下面的“处理点击次数和展示次数”一节。

由于单个广告单元可以设置为投放多个广告素材模板,因此可以使用唯一模板 ID 多次调用 forCustomTemplateAd,以便为多个可能的自定义原生广告格式准备广告加载程序。

模板 ID

可以在 DFP 界面投放标签的广告素材 > 原生广告格式部分找到用于唯一引用原生自定义广告格式的模板 ID:

每个自定义原生广告格式的模板 ID 显示在其名称下方。点击其中一个名称可以转到详细信息屏幕,其中显示有关模板字段的信息:

从这里,可以添加、修改和移除各个字段。请注意右侧的变量 ID 列。这些 ID 用于访问各个素材资源,具体细节将在下一部分讨论。

展示自定义原生广告格式

自定义原生广告格式与系统定义的原生广告格式的不同之处在于,发布商有权定义自己的构成广告的“模板”(即素材资源列表)。因此,与系统定义的格式相比,展示自定义原生广告的过程在以下几个方面有所不同:

  1. 因为 NativeCustomTemplateAd 类用于处理您在 DFP 中定义的任何自定义原生广告格式,因此它没有命名的素材资源 get 程序。相反,它提供了与将模板字段的变量 ID 作为参数的 getTextgetImage 方法类似的方法。
  2. 没有类似于 NativeContentAdView 的可用于 NativeCustomTemplateAd 的专用广告视图类。您可以自由使用 FrameLayout、RelativeLayout 或任何有助于改善您的用户体验的广告视图类。
  3. 因为没有专用的 ViewGroup 类,所以您不需要注册任何用于展示广告素材资源的视图。这会在展示广告时节省几行代码,但也意味着您以后需要做一点额外的工作来处理点击。

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

public void displayCustomTemplateAd (ViewGroup parent,
                                     NativeCustomTemplateAd customTemplateAd) {
    // Inflate a layout and add it to the parent ViewGroup.
    LayoutInflater inflater = (LayoutInflater) parent.getContext()
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View adView = inflater.inflate(R.layout.custom_template_ad, parent);

    // Locate the TextView that will hold the value for "Headline" and
    // set its text.
    TextView myHeadlineView = (TextView) adView.findViewById(R.id.headline);
    myHeadlineView.setText(customTemplateAd.getText("Headline"));

    // Locate the ImageView that will hold the value for "MainImage" and
    // set its drawable.
    Button myMainImageView = (ImageView) adView.findViewById(R.id.main_image);
    myMainImageView.setImageDrawable(
            nativeCustomTemplateAd.getImage("MainImage").getDrawable());

    ...
    // Continue locating views and displaying assets until finished.
    ...
}

处理自定义原生广告格式的点击次数和展示次数

使用自定义原生广告格式时,您的应用负责记录展示次数并向 SDK 报告点击事件。

记录展示次数

要记录自定义模板广告的展示次数,只需在相应 NativeCustomTemplateAd 上调用 recordImpression 方法:

myCustomTemplateAd.recordImpression();

如果您的应用偶然针对同一个广告调用该方法两次,则 SDK 会自动阻止系统针对单个请求重复记录展示。

报告点击次数

要向 SDK 报告在素材资源视图中发生了点击,请在相应 NativeCustomTemplateAd 上调用 performClick 方法,并传入所点击素材资源的名称。例如,如果您的自定义模板中有一个名为“MainImage”的素材资源,并希望报告与该素材资源对应的 ImageView 上的点击,则代码如下所示:

myCustomTemplateAd.performClick("MainImage");

请注意,您不需要为与广告相关联的每个视图调用此方法。例如,如果您有另一个名为“Caption”的字段可供展示,但没有被用户点击或点按,则您的应用不需要为该素材资源的视图调用 performClick

响应自定义点击操作

当对自定义模板广告执行点击时,SDK 会有三种可能的响应,按以下顺序尝试:

  1. AdLoader 调用 OnCustomClickListener(如果已提供)。
  2. 对于每个广告的深层链接网址,尝试查找内容解析器并启动要解析的第一个网址。
  3. 打开浏览器并导航到广告的传统目标网址。

forCustomTemplateAd 方法接受 OnCustomClickListener。如果您传入监听器对象,SDK 将改为调用其 onCustomClick 方法,并且不会采取进一步操作。但是,如果您传递一个 null 值作为监听器,SDK 将会退回到广告中注册的深层链接和/或目标网址。

自定义点击监听器可让您的应用决定响应点击的最佳操作,无论是更新界面,启动新活动还是仅记录点击。以下是一个简单记录发生点击的示例:

AdLoader adLoader = new AdLoader.Builder(context, "/6499/example/native")
    .forCustomTemplateAd("10063170",
      new NativeCustomTemplateAd.OnCustomTemplateAdLoadedListener() {
        // Display the ad.
      },
      new NativeCustomTemplateAd.OnCustomClickListener() {
          @Override
          public void onCustomClick(NativeCustomTemplateAd ad, String assetName) {
            Log.i("MyApp", "A custom click just happened for " + assetName + "!");
          }
      }).build();

乍一看,自定义点击监听器的存在似乎很奇怪。毕竟,您的应用刚刚告诉 SDK 发生了一次点击,为什么 SDK 应该反过来向应用报告?

此信息流的存在有几个原因,但最重要的是它允许 SDK 保持对点击响应的控制。例如,它可以自动对已为广告素材设置的第三方跟踪网址执行 ping 操作,并处理后台的其他任务,而不需要任何附加代码。

测试原生广告代码

直销广告

如果您想测试直销原生广告的呈现效果,可以使用此 DFP 广告单元 ID:

/6499/example/native

它已配置为投放示例应用安装广告和内容广告以及包含以下素材资源的自定义原生广告格式:

  • Headline(文字)
  • MainImage(图片)
  • Caption(文字)

自定义原生广告格式的模板 ID 为 10063170。

原生补余广告

要测试原生补余广告的行为,请使用此 DFP 广告单元:

/6499/example/native-backfill

它将投放包含广告选择叠加层的示例应用安装广告和内容广告。

在实际投放前,请务必更新代码,确保在其中引用您的实际广告单元和模板 ID!

发送以下问题的反馈:

此网页
SDK for DFP Users on Android
需要帮助?请访问我们的支持页面