原生广告自定义事件

前提条件

完成自定义事件设置

请求原生广告

当到达广告瀑布流中介链中的自定义事件订单项时, 系统将对您提供的类名称调用 loadNativeAd() 方法, 创建自定义 事件。在此示例中 该方法位于 SampleCustomEvent 中,然后由后者调用 SampleNativeCustomEventLoader 中的 loadNativeAd() 方法。

要请求原生广告,请创建或修改一个类,该类可以扩展 Adapter 以 实现 loadNativeAd()。如果已经存在扩展 Adapter 的类, 在此处实现 loadNativeAd()。此外,创建一个新类来实现 UnifiedNativeAdMapper

在我们的自定义事件示例中, SampleCustomEvent 会扩展 Adapter 类,然后委托给 SampleNativeCustomEventLoader

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.Adapter;
import com.google.android.gms.ads.mediation.MediationAdConfiguration;
import com.google.android.gms.ads.mediation.MediationAdLoadCallback;

import com.google.android.gms.ads.mediation.MediationNativeAdCallback;
...
public class SampleCustomEvent extends Adapter {
  private SampleNativeCustomEventLoader nativeLoader;

  @Override
  public void loadNativeAd(
      @NonNull MediationNativeAdConfiguration adConfiguration,
      @NonNull MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback> callback) {
    nativeLoader = new SampleNativeCustomEventLoader(adConfiguration, callback);
    nativeLoader.loadAd();
  }
}

SampleNativeCustomEventLoader 负责以下任务:

  • 加载原生广告。

  • 实现 UnifiedNativeAdMapper 类。

  • 接收广告事件回调并向 Google 移动广告 SDK 报告。

Ad Manager 界面中定义的可选参数是 包含的广告配置中可以通过 adConfiguration.getServerParameters().getString(MediationConfiguration.CUSTOM_EVENT_SERVER_PARAMETER_FIELD)。 此参数通常是广告联盟 SDK 所需的资源。

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.Adapter;
import com.google.android.gms.ads.mediation.MediationNativeAdConfiguration;
import com.google.android.gms.ads.mediation.MediationAdLoadCallback;
import com.google.android.gms.ads.mediation.MediationNativeAdCallback;
...

public class SampleNativeCustomEventLoader extends SampleNativeAdListener {
  /** Configuration for requesting the native ad from the third-party network. */
  private final MediationNativeAdConfiguration mediationNativeAdConfiguration;

  /** Callback that fires on loading success or failure. */
  private final MediationAdLoadCallback<UnifiedNativeAdMapper, MediationNativeAdCallback>
      mediationAdLoadCallback;

  /** Callback for native ad events. */
  private MediationNativeAdCallback nativeAdCallback;

  /** Constructor */
  public SampleNativeCustomEventLoader(
      @NonNull MediationNativeAdConfiguration mediationNativeAdConfiguration,
      @NonNull MediationAdLoadCallback<MediationNativeAd, MediationNativeAdCallback>
              mediationAdLoadCallback) {
    this.mediationNativeAdConfiguration = mediationNativeAdConfiguration;
    this.mediationAdLoadCallback = mediationAdLoadCallback;
  }

  /** Loads the native ad from the third-party ad network. */
  public void loadAd() {
    // Create one of the Sample SDK's ad loaders to request ads.
    Log.i("NativeCustomEvent", "Begin loading native ad.");
    SampleNativeAdLoader loader =
        new SampleNativeAdLoader(mediationNativeAdConfiguration.getContext());

    // All custom events have a server parameter named "parameter" that returns
    // back the parameter entered into the UI when defining the custom event.
    String serverParameter = mediationNativeAdConfiguration
        .getServerParameters()
        .getString(MediationConfiguration
        .CUSTOM_EVENT_SERVER_PARAMETER_FIELD);
    Log.d("NativeCustomEvent", "Received server parameter.");

    loader.setAdUnit(serverParameter);

    // Create a native request to give to the SampleNativeAdLoader.
    SampleNativeAdRequest request = new SampleNativeAdRequest();
    NativeAdOptions options = mediationNativeAdConfiguration.getNativeAdOptions();
    if (options != null) {
      // If the NativeAdOptions' shouldReturnUrlsForImageAssets is true, the adapter should
      // send just the URLs for the images.
      request.setShouldDownloadImages(!options.shouldReturnUrlsForImageAssets());

      request.setShouldDownloadMultipleImages(options.shouldRequestMultipleImages());
      switch (options.getMediaAspectRatio()) {
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_LANDSCAPE:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_LANDSCAPE);
          break;
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_PORTRAIT:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_PORTRAIT);
          break;
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_SQUARE:
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_ANY:
        case NativeAdOptions.NATIVE_MEDIA_ASPECT_RATIO_UNKNOWN:
        default:
          request.setPreferredImageOrientation(SampleNativeAdRequest.IMAGE_ORIENTATION_ANY);
      }
    }

    loader.setNativeAdListener(this);

    // Begin a request.
    Log.i("NativeCustomEvent", "Start fetching native ad.");
    loader.fetchAd(request);
  }
}

根据广告是成功抓取还是遇到错误,您可以 会调用 onSuccess()onFailure()onSuccess() 的调用方法为:传入实现 MediationNativeAd

通常,这些方法是在 适配器实现的第三方 SDK。在本示例中,示例 SDK 具有带有相关回调的 SampleAdListener

Java

@Override
public void onNativeAdFetched(SampleNativeAd ad) {
  SampleUnifiedNativeAdMapper mapper = new SampleUnifiedNativeAdMapper(ad);
  mediationNativeAdCallback = mediationAdLoadCallback.onSuccess(mapper);
}

@Override
public void onAdFetchFailed(SampleErrorCode errorCode) {
  mediationAdLoadCallback.onFailure(SampleCustomEventError.createSampleSdkError(errorCode));
}

映射原生广告

对于原生广告,不同的 SDK 都有自己独特的广告格式。你可能会回来 包含“title”的对象字段,而另一个字段可能 “headline”此外,用于跟踪展示和处理 点击次数可能因 SDK 而异。

UnifiedNativeAdMapper负责协调这些差异, 调整参与中介的 SDK 的原生广告对象,使其与 Google 移动广告 SDK自定义事件应扩展此类以创建 他们自己的参与中介的 SDK 专属的映射器。以下是 Google Ads 提供的 我们的示例自定义事件项目:

Java

package com.google.ads.mediation.sample.customevent;

import com.google.android.gms.ads.mediation.UnifiedNativeAdMapper;
import com.google.android.gms.ads.nativead.NativeAd;
...

public class SampleUnifiedNativeAdMapper extends UnifiedNativeAdMapper {

  private final SampleNativeAd sampleAd;

  public SampleUnifiedNativeAdMapper(SampleNativeAd ad) {
    sampleAd = ad;
    setHeadline(sampleAd.getHeadline());
    setBody(sampleAd.getBody());
    setCallToAction(sampleAd.getCallToAction());
    setStarRating(sampleAd.getStarRating());
    setStore(sampleAd.getStoreName());
    setIcon(
        new SampleNativeMappedImage(
            ad.getIcon(), ad.getIconUri(), SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));
    setAdvertiser(ad.getAdvertiser());

    List<NativeAd.Image> imagesList = new ArrayList<NativeAd.Image>();
    imagesList.add(new SampleNativeMappedImage(ad.getImage(), ad.getImageUri(),
        SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));
    setImages(imagesList);

    if (sampleAd.getPrice() != null) {
      NumberFormat formatter = NumberFormat.getCurrencyInstance();
      String priceString = formatter.format(sampleAd.getPrice());
      setPrice(priceString);
    }

    Bundle extras = new Bundle();
    extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, ad.getDegreeOfAwesomeness());
    this.setExtras(extras);

    setOverrideClickHandling(false);
    setOverrideImpressionRecording(false);

    setAdChoicesContent(sampleAd.getInformationIcon());
  }

  @Override
  public void recordImpression() {
    sampleAd.recordImpression();
  }

  @Override
  public void handleClick(View view) {
    sampleAd.handleClick(view);
  }

  // The Sample SDK doesn't do its own impression/click tracking, instead relies on its
  // publishers calling the recordImpression and handleClick methods on its native ad object. So
  // there's no need to pass a reference to the View being used to display the native ad. If
  // your mediated network does need a reference to the view, the following method can be used
  // to provide one.

  @Override
  public void trackViews(View containerView, Map<String, View> clickableAssetViews,
      Map<String, View> nonClickableAssetViews) {
    super.trackViews(containerView, clickableAssetViews, nonClickableAssetViews);
    // If your ad network SDK does its own impression tracking, here is where you can track the
    // top level native ad view and its individual asset views.
  }

  @Override
  public void untrackView(View view) {
    super.untrackView(view);
    // Here you would remove any trackers from the View added in trackView.
  }
}

现在,我们来详细了解构造函数代码。

保留对参与中介的原生广告对象的引用

构造函数接受 SampleNativeAd 参数,即所使用的原生广告类 。映射器需要引用 中介广告,因此可以传递点击和展示事件。“SampleNativeAd”现为 存储为局部变量。

设置映射的素材资源属性

构造函数使用 SampleNativeAd 对象在 UnifiedNativeAdMapper

此代码段可获取参与中介的广告的价格数据,并用该数据设置映射器的 价格:

Java

if (sampleAd.getPrice() != null) {
    NumberFormat formatter = NumberFormat.getCurrencyInstance();
    String priceString = formatter.format(sampleAd.getPrice());
    setPrice(priceString);
}

在本例中,参与中介的广告将价格存储为 double,而 Ad Manager 针对同一素材资源使用了 String。通过 映射器负责处理这些类型的转换。

映射图片素材资源

映射图片素材资源比映射数据类型(例如 doubleString。图片可能会自动下载, 以网址值的形式返回。它们的“像素与 dpi 的比例”也可能会变化。

为帮助您管理这些详细信息,Google 移动广告 SDK 提供了 NativeAd.Image 类。这与需要创建子类的方式大致相同 UnifiedNativeAdMapper 来映射参与中介的原生广告,您还应该创建一个 是 NativeAd.Image 的子类。

下面是自定义事件的 SampleNativeMappedImage 类的示例:

Java

public class SampleNativeMappedImage extends NativeAd.Image {

  private Drawable drawable;
  private Uri imageUri;
  private double scale;

  public SampleNativeMappedImage(Drawable drawable, Uri imageUri, double scale) {
    this.drawable = drawable;
    this.imageUri = imageUri;
    this.scale = scale;
  }

  @Override
  public Drawable getDrawable() {
    return drawable;
  }

  @Override
  public Uri getUri() {
    return imageUri;
  }

  @Override
  public double getScale() {
    return scale;
  }
}

以下代码行中的 SampleNativeAdMapper 使用其映射的图像类来设置 映射器的图标图片资源:

Java

setIcon(new SampleNativeMappedImage(ad.getAppIcon(), ad.getAppIconUri(),
    SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE));

向 extras 包添加字段

除了 Ad Manager 原生广告格式。UnifiedNativeAdMapper 类包含一个 setExtras() 方法,用于将这些素材资源传递给 发布商。SampleNativeAdMapper 将其用于示例 SDK 的 "超棒程度"资产:

Java

Bundle extras = new Bundle();
extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, ad.getDegreeOfAwesomeness());
this.setExtras(extras);

发布商可以使用 NativeAd 类的getExtras() 方法。

广告选择

您的自定义事件负责使用 UnifiedNativeAdMapper 上的 setAdChoicesContent() 方法。以下是来自 SampleNativeAdMapper,其中展示了如何提供“广告选择”图标:

Java

public SampleNativeAdMapper(SampleNativeAd ad) {
    ...
    setAdChoicesContent(sampleAd.getInformationIcon());
}

展示事件和点击事件

Google 移动广告 SDK 和参与中介的 SDK 都需要知道 展示或点击,但只需要有一个 SDK 跟踪这些事件。那里 是自定义事件可以使用两种不同的方法,具体取决于 参与中介的 SDK 支持自行跟踪展示次数和点击次数。

使用 Google 移动广告 SDK 跟踪点击和展示

如果参与中介的 SDK 并非自行执行展示和点击跟踪, 提供了记录点击次数和展示次数的方法,Google 移动广告 SDK 可以 跟踪这些事件并通知适配器。通过 UnifiedNativeAdMapper 类包含两个方法: recordImpression()handleClick() 通过实现自定义事件,您可以对参与中介的 原生广告对象:

Java

@Override
public void recordImpression() {
  sampleAd.recordImpression();
}

@Override
public void handleClick(View view) {
  sampleAd.handleClick(view);
}

由于 SampleNativeAdMapper 存储着对示例 SDK 的原生代码的引用, 它可以调用该对象中的相应方法来报告点击 。请注意,handleClick() 方法接受 单个参数:与指定原生广告素材资源的 View 对象 获得点击。

使用参与中介的 SDK 跟踪点击和展示

一些参与中介的 SDK 可能偏好自行跟踪点击和展示。在 在这种情况下,您应将默认的点击和展示跟踪方法替换为 并在其中进行以下两个调用: UnifiedNativeAdMapper

Java

setOverrideClickHandling(true);
setOverrideImpressionRecording(true);

覆盖点击跟踪和展示跟踪的自定义事件必须 向 Google 移动报告 onAdClicked()onAdImpression() 事件 广告 SDK。

要跟踪展示次数和点击次数,参与中介的 SDK 可能需要 启用跟踪。自定义事件应覆盖 trackViews() 方法,并使用它将原生广告的视图传递给参与中介的 要跟踪的 SDK。我们的自定义事件示例项目中的示例 SDK 本指南中的代码段)未采用此方法;但如果 那么自定义事件代码将如下所示:

Java

@Override
public void trackViews(View containerView,
    Map<String, View> clickableAssetViews,
    Map<String, View> nonClickableAssetViews) {
  sampleAd.setNativeAdViewForTracking(containerView);
}

如果参与中介的 SDK 支持跟踪具体素材资源,则可深入了解 clickableAssetViews,用于了解应将哪些视图设置为可点击。这张地图是 由 NativeAdAssetNames 中的素材资源名称键控。UnifiedNativeAdMapper 提供相应的 untrackView() 方法,自定义事件可以替换该方法 释放对视图的所有引用并解除它与原生广告的关联 对象。

将中介事件转发至 Google 移动广告 SDK

您可以在 MediationNativeAdCallback 文档

请务必确保您的自定义事件转发的回调数量与 这样您的应用才能从 Google 移动广告 SDK。下面是一个使用回调的示例:

至此,我们为原生广告完成了自定义事件的实现。完整示例 可通过以下平台观看: GitHub