前提条件
完成自定义事件设置。
请求原生广告
在达到广告瀑布流中介链内的自定义事件订单项时,
系统会对您在创建自定义事件时提供的类名称调用 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