前提条件
完成自定义事件设置。
请求原生广告
在达到广告瀑布流中介链内的自定义事件订单项时,
系统会对您在创建自定义事件时提供的类名称调用 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 Mobile Ads 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()。
系统会通过传入实现 MediationNativeAd 的类的实例来调用 onSuccess()。
通常,这些方法是在您的适配器所实现的第三方 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 都有自己独特的广告格式。例如,一个 SDK 可能返回包含“title”字段的对象,而另一个 SDK 返回的对象可能包含“headline”字段。此外,用于跟踪展示和处理点击的方法也可能会因 SDK 而异。
UnifiedNativeAdMapper 负责调和这些差异,并
调整参与中介的 SDK 的原生广告对象,使其与
Google Mobile Ads SDK 预期的接口相匹配。自定义事件应扩展此类,以创建专属于它们参与中介的 SDK 的映射器。以下是我们的示例自定义事件项目中的一个示例广告映射器:
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 参数,这是示例 SDK 对其原生广告采用的原生广告类。映射器需要引用参与中介的广告才能传递点击和展示事件。SampleNativeAd 存储为局部变量。
设置映射的素材资源属性
构造函数使用 SampleNativeAd 对象在 UnifiedNativeAdMapper 中填充素材资源。
以下代码段可获取参与中介的广告的价格数据,然后用该数据设置映射器的价格:
Java
if (sampleAd.getPrice() != null) { NumberFormat formatter = NumberFormat.getCurrencyInstance(); String priceString = formatter.format(sampleAd.getPrice()); setPrice(priceString); }
在此示例中,参与中介的广告将价格存储为 double,而 Ad Manager 对同一素材资源使用 String。映射器负责处理这些类型的转换。
映射图片素材资源
与映射 double 或 String 等数据类型相比,映射图片素材资源会复杂一些。图片既可以自动下载,也可以作为网址值返回,而且其“像素与 dpi 的比例”可能也不尽相同。
为了帮助您管理这些详细信息,Google Mobile Ads 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));
向额外信息 Bundle 添加字段
除了 Ad Manager 原生广告格式中的素材资源之外,一些参与中介的 SDK 还会提供额外的素材资源。UnifiedNativeAdMapper 类包含一个 setExtras() 方法,用于将这些素材资源传递给发布商。SampleNativeAdMapper 就是采用此方法来传递示例 SDK 的“degree of awesomeness”素材资源:
Java
Bundle extras = new Bundle(); extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, ad.getDegreeOfAwesomeness()); this.setExtras(extras);
发布商可以使用 NativeAd 类的 getExtras() 方法检索数据。
AdChoices
您的自定义事件负责使用 UnifiedNativeAdMapper 中的 setAdChoicesContent() 方法提供“广告选择”图标。以下是 SampleNativeAdMapper 中的一段代码段,展示了如何提供“广告选项”图标:
Java
public SampleNativeAdMapper(SampleNativeAd ad) { ... setAdChoicesContent(sampleAd.getInformationIcon()); }
展示和点击事件
Google Mobile Ads SDK 和参与中介的 SDK 都需要知道展示或点击发生的时间,但只需要有一个 SDK 跟踪这些事件。有两种不同做法可供自定义事件选用,具体取决于参与中介的 SDK 是否支持自行跟踪展示和点击。
使用 Google Mobile Ads SDK 跟踪点击和展示
如果参与中介的 SDK 不自行执行展示和点击跟踪,但提供了记录点击和展示的方法,则 Google Mobile Ads 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 移动广告 SDK 报告 onAdClicked() 和 onAdImpression() 事件。
如需跟踪展示和点击,参与中介的 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 Mobile Ads SDK
您可以在
MediationNativeAdCallback 文档中找到中介支持的所有回调。
您的自定义事件必须尽可能多地转发这些回调,以便您的应用从 Google Mobile Ads SDK 接收这些等效事件。以下是使用回调的示例:
到这里,我们已经实现针对原生广告的自定义事件。GitHub 上提供了完整的示例 GitHub