原生广告

原生广告是一种布局可以在应用级别定义的广告类型。这一功能允许您根据应用设计的具体上下文更改广告的视觉风格以及投放位置。

原生广告可以增强广告体验。因此,您可以在不失去用户兴趣的情况下展示更多广告。从长远来看,这确保了广告收入的最大化。

广告呈现通过本地平台工具执行,从而提高广告效果和质量。

外观

本指南介绍了将原生广告集成到 Android 应用的过程。 除了代码示例和说明之外,它还包含特定格式的建议以及指向其他资源的链接。

前提条件

  1. 按照快速入门 中描述的 SDK 集成步骤进行操作。
  2. 首先,您需要初始化 广告 SDK。
  3. 确保您使用的是最新Yandex Mobile Ads SDK 版本。如果您使用的是广告中介服务,请更新至最新的单一构建版本

实施

集成原生广告的关键步骤:

  • 创建并配置名为 NativeAdLoader 的广告加载器。
  • 注册广告加载器事件监听器。
  • 加载广告。
  • 渲染加载的广告。

原生广告集成的具体注意事项

  1. 所有 Yandex Mobile Ads SDK 方法调用都必须在主线程中进行。

  2. 如果 onAdFailedToLoad() 回调返回错误,请勿尝试再次加载新广告。 如果没有其他选项,请限制广告加载重试次数。 如果有限制,这将有助于避免频繁出现失败的请求和连接问题。

  3. 我们建议您在发生广告交互的屏幕的整个生命周期内保持对广告及其加载器的强引用。

  4. 广告容器的大小应以广告内容为准。 广告完成加载后,需要渲染其所有素材。 您可以从 NativeAd 广告对象获取可用广告素材的列表。

  5. 视频广告通常会产生最佳效果。 要展示视频广告,广告容器和 MediaView 素材的大小必须至少为 300×160 dp(密度无关像素)。

  6. 我们建议使用包含所有可能素材的布局。 从实际角度来看,这样的布局会导致更高的转化率。

  1. 顶部不可点击安全区域的高度为 80 dp。该区域内的控件可以点击。

  2. 视觉元素(素材)的尺寸必须至少为 32×32 dp,包括关闭按钮及其他所有图标。

  3. 素材周围的可点击区域必须至少为 64×64 dp。例如,如果素材的尺寸为 32×32 dp,则其四周需有足够的内边距,以确保总可点击区域达到 64×64 dp。

  4. 如果控件有延迟出现,必须显示一个计时器或进度条,直到元素加载完成。

示例

加载广告

要加载原生广告,请创建 NativeAdLoader 对象。

广告请求参数通过 NativeAdRequestConfiguration.Builder 类对象进行配置。 在请求参数中,可以传递广告单元 ID、图片加载方式、年龄、性别属性,以及其他可以使展示更具相关性的数据。 详情请参阅广告定位部分。

要接收有关广告加载结果的通知,请创建 NativeAdLoadListener 实例并将其设置为广告加载器事件监听器。

要加载广告,请调用 loadAd() 方法。

以下示例展示了如何从活动加载原生广告:

class CustomNativeAdActivity : AppCompatActivity(R.layout.activity_custom_native_ad) {

  private val nativeAdView get() = binding.nativeAd.root

  private var nativeAdLoader: NativeAdLoader? = null

  private lateinit var binding: ActivityCustomNativeAdBinding

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

      nativeAdLoader = createNativeAdLoader()
      nativeAdLoader?.loadAd(
          // 可在此处使用 NativeAdRequestConfiguration.Builder 类中的方法指定各个选项设置。
          NativeAdRequestConfiguration.Builder("your-ad-unit-id").build())
  }

  private fun createNativeAdLoader(): NativeAdLoader {
      return nativeAdLoader ?: NativeAdLoader(this).apply {
          setNativeAdLoadListener(object : NativeAdLoadListener {
              override fun onAdLoaded(p0: NativeAd) {
                  // 广告已成功加载。 现在您可以展示已加载的广告。
              }

              override fun onAdFailedToLoad(p0: AdRequestError) {
                  // 广告因 AdRequestError 无法加载。
                  // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
              }
          })
      }
  }
}
class CustomNativeAdActivity extends AppCompatActivity {
  private NativeAdView mNativeAdView = mBinding.nativeAd.getRoot();

  @Nullable private NativeAdLoader mNativeAdLoader = null;

  private ActivityCustomNativeAdBinding mBinding;

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      mBinding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
      setContentView(mBinding.getRoot());

      mNativeAdLoader = createNativeAdLoader();
      if (mNativeAdLoader != null) {
          // 可在此处使用 NativeAdRequestConfiguration.Builder 类中的方法指定各个选项设置。
          mNativeAdLoader.loadAd(
                  new NativeAdRequestConfiguration.Builder("your-ad-unit-id").build()
          );
      }
  }

  private NativeAdLoader createNativeAdLoader() {
      if (mNativeAdLoader != null) {
          return mNativeAdLoader;
      }

      final NativeAdLoader newNativeAdLoader = new NativeAdLoader(this);
      newNativeAdLoader.setNativeAdLoadListener(new NativeAdLoadListener() {
          @Override
          public void onAdLoaded(@NonNull final NativeAd nativeAd) {
              // 广告已成功加载。 现在您可以展示已加载的广告。
          }

          @Override
          public void onAdFailedToLoad(@NonNull final AdRequestError error) {
              // 广告因 AdRequestError 无法加载。
              // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
          }
      });
      return newNativeAdLoader;
  }
}

如果您通过 Adfox 投放广告,则在横幅广告响应后,可以使用 AdAttributes 类型的 adAttributes 属性从 NativeAdBannerAdView 对象访问 campaignIdbannerIdplaceId 数据。

展示广告

广告完成加载后,需要渲染其所有素材。 您可以从 NativeAd 广告对象获取可用广告素材的列表。

手动配置原生广告布局

此方法允许您为原生广告创建自定义布局,并定义广告之间的相对位置。 广告中可能包含必需和可选的展示素材。 要查看完整列表,请参阅原生广告素材

提示

我们建议使用包含所有可能素材的布局。 从实际角度来看,这样的布局会导致更高的转化率。

对于每个广告素材,通过 NativeAdViewBinder.Builder 类的实例提供视图。 该类接受 NativeAdView 容器作为参数。 确保将所有广告素材定义为此容器的子视图。

将现成广告布局链接到 NativeAd 对象。

示例代码
private fun showAd(nativeAd: NativeAd) {
    val nativeAdViewBinder = binding.nativeAd.run {
        NativeAdViewBinder.Builder(nativeAdView)
            .setAgeView(age)
            .setBodyView(body)
            .setCallToActionView(callToAction)
            .setDomainView(domain)
            .setFaviconView(favicon)
            .setFeedbackView(feedback)
            .setIconView(icon)
            .setMediaView(media)
            .setPriceView(price)
            .setRatingView(rating)
            .setReviewCountView(reviewCount)
            .setSponsoredView(sponsored)
            .setTitleView(title)
            .setWarningView(warning)
            .build()
    }

    try {
        nativeAd.bindNativeAd(nativeAdViewBinder)
        nativeAd.setNativeAdEventListener(NativeAdEventLogger())
    } catch (exception: NativeAdException) {
        Logger.error(exception.message.orEmpty())
    }
}

private inner class NativeAdEventLogger : NativeAdEventListener {

    override fun onAdClicked() {
        // 记录广告点击时调用。
    }

    override fun onLeftApplication() {
        // 当用户由于点击广告而即将离开应用程序(例如,前往浏览器)时调用。
    }

    override fun onReturnedToApplication() {
        // 当用户点击后返回应用程序时调用。
    }

    override fun onImpression(data: ImpressionData?) {
        // 记录广告展示时调用。
    }
}
private void showAd(@NonNull final NativeAd nativeAd) {
    final NativeAdViewBinder nativeAdViewBinder = new NativeAdViewBinder.Builder(mNativeAdView)
            .setAgeView(age)
            .setBodyView(body)
            .setCallToActionView(callToAction)
            .setDomainView(domain)
            .setFaviconView(favicon)
            .setFeedbackView(feedback)
            .setIconView(icon)
            .setMediaView(media)
            .setPriceView(price)
            .setRatingView(rating)
            .setReviewCountView(reviewCount)
            .setSponsoredView(sponsored)
            .setTitleView(title)
            .setWarningView(warning)
            .build();
    try {
        nativeAd.bindNativeAd(nativeAdViewBinder);
        nativeAd.setNativeAdEventListener(new CustomNativeAdActivity.NativeAdEventLogger());
    } catch (final NativeAdException exception) {
        Log.e("TAG", exception.getMessage());
    }
}

private class NativeAdEventLogger implements NativeAdEventListener {
    @Override
    public void onAdClicked() {
        // 记录广告点击时调用。
    }

    @Override
    public void onLeftApplication() {
        // 当用户由于点击广告而即将离开应用程序(例如,前往浏览器)时调用。
    }

    @Override
    public void onReturnedToApplication() {
        // 当用户点击后返回应用程序时调用。
    }

    @Override
    public void onImpression(@Nullable ImpressionData data) {
        // 记录广告展示时调用。
    }
}

加载多个广告

Yandex Mobile Ads SDK 提供在单个请求中加载多个广告的选项(最多九个广告)。

要发出批量广告请求,请使用 NativeBulkAdLoader 类的实例。 它接受 loadAds 方法中的 count 参数,用于确定每个请求所需的广告数量。

示例代码
class NativeBulkAdLoaderActivity : AppCompatActivity(R.layout.activity_custom_native_ad) {

    private val nativeAdView get() = binding.nativeAd.root

    private var nativeAdsLoader: NativeBulkAdLoader? = null

    private lateinit var binding: ActivityCustomNativeAdBinding

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

        nativeAdsLoader = createNativeBulkAdLoader()
        // 可在此处使用 NativeAdRequestConfiguration.Builder 类中的方法指定各个选项设置。
        val adRequestConfiguration = NativeAdRequestConfiguration.Builder("your-ad-unit-id").build()
        nativeAdsLoader?.loadAds(adRequestConfiguration, 3)
    }

    private fun createNativeBulkAdLoader(): NativeBulkAdLoader {
        return nativeAdsLoader ?: NativeBulkAdLoader(this).apply {
            setNativeBulkAdLoadListener(object : NativeBulkAdLoadListener {
                override fun onAdsLoaded(p0: MutableList<NativeAd>) {
                    // 广告已成功加载。 现在您可以显示已加载的广告。
                    for (nativeAd in p0) {
                        showAd(nativeAd)
                    }
                }

                override fun onAdsFailedToLoad(p0: AdRequestError) {
                    // 广告因 AdRequestError 无法加载。
                    // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
                }
            })
        }
    }
}
class CustomBulkNativeAdActivity extends AppCompatActivity {
    private NativeAdView mNativeAdView = mBinding.nativeAd.getRoot();

    @Nullable private NativeBulkAdLoader mNativeAdsLoader = null;

    private ActivityCustomNativeAdBinding mBinding;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mBinding = ActivityCustomNativeAdBinding.inflate(getLayoutInflater());
        setContentView(mBinding.getRoot());

        mNativeAdsLoader = createNativeBulkAdLoader();
        if (mNativeAdsLoader != null) {
            // 可在此处使用 NativeAdRequestConfiguration.Builder 类中的方法指定各个选项设置。
            mNativeAdsLoader.loadAds(
                    new NativeAdRequestConfiguration.Builder("your-ad-unit-id").build();
            );
        }
    }

    private NativeBulkAdLoader createNativeBulkAdLoader() {
        if (mNativeAdsLoader != null) {
            return mNativeAdsLoader;
        }

        final NativeBulkAdLoader newNativeBulkAdLoader = new NativeBulkAdLoader(this);

        newNativeBulkAdLoader.setNativeBulkAdLoadListener(new NativeBulkAdLoadListener() {
            @Override
            public void onAdsLoaded(@NonNull final List<NativeAd> list) {
                // 广告已成功加载。 现在您可以展示已加载的广告。
            }

            @Override
            public void onAdsFailedToLoad(@NonNull final AdRequestError error) {
                // 广告因 AdRequestError 无法加载。
                // 强烈建议不要尝试通过 onAdFailedToLoad() 方法加载新广告。
            }
        });
        return newNativeBulkAdLoader;
    }
}

备注

使用批量广告请求,您可以选择多个不同的广告。

批量请求返回的广告数组可能包含 0 到 countNativeAd 对象。 所有接收到的广告对象均可以独立展示,使用之前描述的原生广告布局方法即可。

测试原生广告集成

使用演示广告单元进行广告测试

使用测试广告检查您的原生广告集成和应用本身。

为了确保每个广告请求都返回测试广告,我们创建了一个特殊的演示广告版位 ID,旨在帮助您测试广告的集成情况。

文字与图片广告的演示 adUnitIddemo-native-content-yandex

移动应用广告的演示 adUnitIddemo-native-app-yandex

重要

在商店中发布您的应用之前,请确保将演示广告版位 ID 替换为在 Yandex Advertising Network 界面中获取的真实 ID。

测试广告集成

您可以使用 SDK 的内置分析器检查原生广告是否正确集成。

该工具检查原生广告是否已正确启用,并向日志输出详细报表。 要查看报表,请在 Logcat(用于调试 Android 应用的工具)中按“YandexAds”关键字进行搜索。

adb logcat -v brief '*:S YandexAds'

如果集成成功,则返回以下消息:

adb logcat -v brief '*:S YandexAds'
mobileads$ adb logcat -v brief '*:S YandexAds'
I/YandexAds(13719): [Integration] Ad type native was integrated successfully

如果存在任何原生广告集成问题,您将获得详细的问题报表和故障排除建议。

原生广告集成正确性指示器

使用此指示器,您可以了解原生广告集成是否成功。 如果没有成功,您可以获取描述问题原因的调试信息。

备注

现在,您可以在调试面板中启用或禁用广告集成正确性指示器。

要在调试模式下启用指示器的显示,请调用 enableDebugErrorIndicator 方法并将其设置为 true

YandexAds.enableDebugErrorIndicator(true)

如果集成成功,在调试模式下,广告上方会出现一个浅绿色边框。

如果原生广告集成出错,在调试模式下,广告上方会出现指示器。 点击指示器即可查看调试消息,该消息应指出问题的根本原因。 再次单击指示器可隐藏该消息。

要在调试模式下禁用指示器的显示,请调用 enableDebugErrorIndicator 方法并将其设置为 false

YandexAds.enableDebugErrorIndicator(false)

视频广告的硬件加速

为了确保视频广告在您的应用屏幕上成功播放,必须启用硬件加速(详情请参阅文档)。

默认情况下,硬件加速已启用。 如果您在应用中禁用了硬件加速,请确保在投放广告的应用屏幕上将其启用。

用于启用硬件加速的代码
<application android:hardwareAccelerated="true">
    <!-- For activities that use ads, hardwareAcceleration should be true. -->
    <activity android:hardwareAccelerated="true" />
</application>