原生自定义事件

本指南适用于希望使用 AdMob 中介功能加载和展示不受 AdMob支持的广告联盟提供的原生广告的发布商。(要了解如何使用 AdMob 中介来加载和展示横幅广告、插页式广告或激励展示广告,请参阅自定义事件。)作为中介适配器类,自定义事件能从其他广告联盟请求广告。当其中一个类的名称添加至广告单元的中介设置后,SDK 就可将其实例化,并通过它获取广告。原生自定义事件类需要能够执行以下任务:

  • 从参与中介的广告联盟处请求原生广告。
  • 将事件从参与中介的广告联盟的 SDK 转发至 Google 移动广告 SDK。
  • 使用 NativeAdMapper 将参与中介的原生广告映射到 AdMob 的原生广告界面。

下文将介绍如何执行各个任务。在我们的 GitHub 代码库中,您还可以找到示例自定义事件项目的完整源代码。

前提条件

要实现 AdMob 自定义事件,必须先将移动广告 SDK 集成到您的项目中。您可能还需要先了解有关如何发出 AdRequest 的信息以及中介的工作原理。

示例 SDK

本指南中的代码段选自我们的示例自定义事件项目,该项目包括了一个“示例 SDK”。我们将在示例中使用这个模拟 SDK 进行演示,介绍如何构建一个使用其他广告联盟的 SDK 进行中介的自定义事件。

示例 SDK 中的类与广告联盟的正式版 SDK 中的类相似。示例 SDK 具有请求对象(例如 SampleNativeAdRequest),广告加载器(例如 SampleNativeAdLoader),以及用于模拟真实广告联盟 SDK 的其他类、常量和界面。不过,示例 SDK 生成的广告是模拟广告,不会产生额外的网络流量。

请求原生广告

requestNativeAd() 方法

自定义事件类必须实现 CustomEventNative 界面,其中包含 Google 移动广告 SDK 用来从自定义事件请求原生广告的方法:

Java

void requestNativeAd(Context context,
        CustomEventNativeListener listener,
        String serverParameter,
        NativeMediationAdRequest mediationAdRequest,
        Bundle customEventExtras);

Kotlin

override fun requestNativeAd(context: Context,
        listener: CustomEventNativeListener,
        serverParameter: String,
        mediationAdRequest: NativeMediationAdRequest,
        customEventExtras: Bundle?)

调用此方法时,自定义事件应从参与中介的广告联盟异步请求原生广告。requestNativeAd() 的以下参数携带了自定义事件在发出请求时可以使用的信息:

  • serverParameter - 将自定义事件添加至广告单元的中介配置时,发布商可输入一个会随各个请求一起传递的字符串值。此参数会保留该值(通常是由参与中介的广告联盟签发的另一个广告单元 ID)。
  • mediationAdRequest - NativeMediationAdRequest 对象,包含单个请求特有的属性,例如请求了哪些原生格式。NativeMediationAdRequestMediationAdRequest 的子类,因此还包含发布商在请求时要提供的其他定位信息的属性。
  • customEventExtras - 包含发布商提供的、与请求相关的所有“额外”信息的 Bundle。创建 AdRequest 时,发布商可使用 addNetworkExtrasBundle() 方法来提供适用于特定中介适配器和自定义事件的信息。本参数包含了发布商为给定的自定义事件类提供的所有额外信息。

除了上述携带请求信息的参数外,还有另外两个参数:

  • context - 可根据自定义事件的需求来使用的 Context 对象。
  • listener - CustomEventNativeListener 对象,自定义事件应使用它来转发事件。

监听器对象极为重要,因为要使用它向 Google 移动广告 SDK 报告事件。本指南会在稍后对此进行介绍。

以下代码段选自我们的示例自定义事件项目,显示了已实现的 requestNativeAd() 方法:

SampleCustomEvent(节选)

Java

@Override
public void requestNativeAd(Context context,
        CustomEventNativeListener customEventNativeListener,
        String serverParameter,
        NativeMediationAdRequest nativeMediationAdRequest,
        Bundle extras) {
    SampleNativeAdLoader loader = new SampleNativeAdLoader(context);
    loader.setAdUnit(serverParameter);

    SampleNativeAdRequest request = new SampleNativeAdRequest();
    NativeAdOptions options = nativeMediationAdRequest.getNativeAdOptions();

    if (options != null) {
        request.setShouldDownloadImages(options.shouldReturnUrlsForImageAssets());
    } else {
        // Set a default value for the one native ad option the Sample SDK supports.
        request.setShouldDownloadImages(true);
    }

    loader.setNativeAdListener(
            new SampleCustomNativeEventForwarder(customEventNativeListener, options));

    loader.fetchAd(request);
}

Kotlin

override fun requestNativeAd(context: Context,
                    customEventNativeListener: CustomEventNativeListener,
                    serverParameter: String,
                    nativeMediationAdRequest: NativeMediationAdRequest,
                    extras: Bundle?) {
    val loader = SampleNativeAdLoader(context)
    loader.setAdUnit(serverParameter)

    val request = SampleNativeAdRequest()
    val options = nativeMediationAdRequest.nativeAdOptions

    request.setShouldDownloadImages(options?.shouldReturnUrlsForImageAssets() ?: true)

    loader.setNativeAdListener(
            SampleCustomNativeEventForwarder(customEventNativeListener, options))

    loader.fetchAd(request)
}

这是一个示例自定义事件,它通过模拟的“示例 SDK”将虚构的广告联盟用作中介。此自定义事件使用 requestNativeAd() 的参数中提供的信息来构建 SampleNativeAdRequest(即示例 SDK 提供的类),然后使用它从示例 SDK 的 SampleNativeAdLoader 请求广告。它还创建了 SampleCustomEventNativeForwarder,以将事件转发回 Google 移动广告 SDK。我们将在下一节介绍该过程。

NativeAdOptions

发出原生广告请求时,发布商会使用 NativeAdOptions 对象指定自己对于该请求的各种偏好,例如,应使用何种方式返回图片素材资源。您的自定义事件需要检查并遵从这些偏好设置。自定义事件可以使用由 NativeMediationAdRequest 对象提供的 getNativeAdOptions() 方法来获取请求的 NativeAdOptions 对象:

Java

NativeAdOptions options = mediationAdRequest.getNativeAdOptions();

Kotlin

val options = mediationAdRequest.nativeAdOptions

获取 NativeAdOptions 后,自定义事件可以读取其属性并执行相应的操作。例如,如果 NativeAdOptions 中的 shouldReturnUrlsForImageAssets 值为 false(默认值),则自定义事件必须返回实际图片素材资源,而不只是网址。在这种情况下,如果用作中介的 SDK 只提供图片的网址,那么自定义事件必须通过这些网址下载图片文件,并在其映射的原生广告中将图片文件的数据提供给发布商。

将事件转发至移动广告 SDK

当自定义事件尝试从参与中介的广告联盟加载原生广告时,可能会发生以下几种情况:SDK 可能会成功返回原生广告,也可能返回错误,或者只报告没有可用的广告。类似地,当用户点按某个广告时,参与中介的 SDK 可能会打开叠加层,也可能会彻底退出应用并启动外部浏览器。对 Google 移动广告 SDK 而言,掌握这些事件非常重要,因此它会向 requestNativeAd() 方法提供一个 CustomEventNativeListener 对象作为参数。

自定义事件的一部分功能就是充当“中间人”,即监听参与中介的 SDK 中的事件,然后根据需要调用相应的 CustomEventNativeListener() 方法。您的自定义事件需要知道以下方法:

  • onAdLoaded() - 此方法应在自定义事件成功加载原生广告时调用。它需要一个类型为 NativeAdMapper 的参数,自定义事件应使用该参数传递刚加载的原生广告的映射版本(NativeAdMapper 类将在下一节中介绍)。
  • onAdFailedToLoad() - 当自定义事件尝试加载原生广告但未能成功时,应使用此方法报告失败。它需要一个整数参数,该参数应被设置为以下错误常量之一:

  • onAdLeftApplication() - 当参与中介的 SDK 导致用户的关注点离开发布商的应用(最常见的是打开外部浏览器)时,调用此方法。

  • onAdOpened() - 如果原生广告为响应用户的点按而打开叠加层或覆盖界面的单独活动(包括外部浏览器),则应调用此方法。如果是打开外部浏览器,则自定义事件应在调用 onAdLeftApplication 之前调用 onAdOpened

  • onAdClosed() - 如果关闭叠加层或覆盖界面的单独活动,则应调用此方法,以表明转由包含原生广告的应用进行控制。

监听器还提供了各种方法,用于报告那些选择自行跟踪点击或展示的自定义事件提供的点击和展示次数,详情请参阅替换默认的点击处理和展示记录方法。一种方法用于向 Google 移动广告 SDK 报告点击,一种方法用于报告展示:

  • onAdClicked() - 此方法应在用户点击原生广告时调用。
  • onAdImpression() - 类似地,此方法应在参与中介的 SDK 记录广告的展示时调用。

有许多方法可以确保事件的正确转发,但最简单的一个方法就是创建专门用作转发器的类。下面就是我们的自定义事件示例项目中提供的这样一个类:

SampleCustomNativeEventForwarder

Java

public class SampleCustomNativeEventForwarder extends SampleNativeAdListener {
    private CustomEventNativeListener nativeListener;
    private NativeAdOptions nativeAdOptions;

    public SampleCustomNativeEventForwarder(
            CustomEventNativeListener listener, NativeAdOptions adOptions) {
        this.nativeListener = listener;
        this.nativeAdOptions = adOptions;
    }

    @Override
    public void onNativeAdFetched(SampleNativeAd ad) {
        SampleUnifiedNativeAdMapper mapper =
                new SampleUnifiedNativeAdMapper(ad, nativeAdOptions);
        nativeListener.onAdLoaded(mapper);
    }

    @Override
    public void onAdFetchFailed(SampleErrorCode errorCode) {
        switch (errorCode) {
            case UNKNOWN:
                nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR);
                break;
            case BAD_REQUEST:
                nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST);
                break;
            case NETWORK_ERROR:
                nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR);
                break;
            case NO_INVENTORY:
                nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL);
                break;
        }
    }
}

Kotlin

class SampleCustomNativeEventForwarder(
        private val nativeListener: CustomEventNativeListener,
        private val nativeAdOptions: NativeAdOptions) : SampleNativeAdListener() {

    fun onNativeAdFetched(ad: SampleNativeAd) {
        val mapper = SampleUnifiedNativeAdMapper(ad, nativeAdOptions)
        nativeListener.onAdLoaded(mapper)
    }

    fun onAdFetchFailed(errorCode: SampleErrorCode) {
        when (errorCode) {
            UNKNOWN -> nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INTERNAL_ERROR)
            BAD_REQUEST -> nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_INVALID_REQUEST)
            NETWORK_ERROR -> nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NETWORK_ERROR)
            NO_INVENTORY -> nativeListener.onAdFailedToLoad(AdRequest.ERROR_CODE_NO_FILL)
        }
    }
}

请注意,此类实现了示例 SDK 的 SampleNativeAdListener 界面。在 SampleCustomEvent(节选)中,已将此转发器类的实例提供给了其 setNativeAdListener() 方法中的 SampleNativeAdLoader

Java

loader.setNativeAdListener(new SampleCustomNativeEventForwarder(customEventNativeListener, options));

Kotlin

loader.setNativeAdListener(SampleCustomNativeEventForwarder(customEventNativeListener, options))

这可确保示例 SDK 在有要报告的事件时调用 SampleCustomNativeEventForwarder 对象的监听器方法(onNativeAdFetched()onAdFetchFailed() 等等)。然后,转发器会调用 Google 移动广告 SDK 的 CustomEventNativeListener 上的相应方法转发事件。简而言之,Google 移动广告 SDK 会监听转发器,而转发器则监听参与中介的 SDK。

上面的 onAdFetchFailed() 示例方法很好地诠释了其中的运行方式。当示例 SDK 加载广告失败时,便会调用转发器的 onAdFetchFailed() 方法,并赋予它错误代码。转发器会检查该错误代码,并通过 Google 移动广告 SDK 使用的一个错误代码调用 CustomEventNativeListeneronAdFailedToLoad() 方法。这样一来,示例 SDK 事件就会转变成了 Google 移动广告 SDK 事件。

映射原生广告

对于原生广告,不同的 SDK 都有自己唯一的广告格式。例如,一个 SDK 可能返回包含“title”字段的对象,而另一个 SDK 返回的可能是包含“headline”字段的对象。此外,用于跟踪展示和处理点击的方法也可能会因 SDK 而异。NativeAdMapper 的任务是消除这些小的差异,并调整参与中介的 SDK 的原生广告对象,使其与 Google 移动广告 SDK 预期的界面相匹配。

AdMob 的统一原生广告格式具有对应的 NativeAdMapper 类:UnifiedNativeAdMapper。自定义事件应创建此类的子类,以创建其参与中介的 SDK 专属的自有映射器。

以下是我们的示例自定义事件项目中的一个示例广告映射器:

SampleUnifiedNativeAdMapper

Java

public class SampleUnifiedNativeAdMapper extends UnifiedNativeAdMapper {

    private final SampleNativeAd sampleAd;
    private NativeAdOptions nativeAdOptions;

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

        List imagesList = new ArrayList();
        imagesList.add(new SampleNativeMappedImage(ad.getImage(), ad.getImageUri(),
                SampleAdapter.SAMPLE_SDK_IMAGE_SCALE));
        setImages(imagesList);

        NumberFormat formatter = NumberFormat.getCurrencyInstance();
        String priceString = formatter.format(sampleAd.getPrice());
        setPrice(priceString);

        Bundle extras = new Bundle();
        extras.putString(SampleAdapter.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);
    }
}

Kotlin

class SampleUnifiedNativeAdMapper(private val sampleAd: SampleNativeAd,
        private val nativeAdOptions: NativeAdOptions) : UnifiedNativeAdMapper() {

    init {
        headline = sampleAd.headline
        body = sampleAd.body
        callToAction = sampleAd.callToAction
        starRating = sampleAd.starRating
        store = sampleAd.storeName
        icon = SampleNativeMappedImage(sampleAd.appIcon, sampleAd.appIconUri,
                SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE)
        advertiser = sampleAd.advertiser

        val imagesList = ArrayList()
        imagesList.add(SampleNativeMappedImage(sampleAd.image, sampleAd.imageUri,
                SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE))
        images = imagesList

        val formatter = NumberFormat.getCurrencyInstance()
        val priceString = formatter.format(sampleAd.price)
        price = priceString

        val extras = Bundle()
        extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, sampleAd.degreeOfAwesomeness)
        this.extras = extras

        overrideClickHandling = false
        overrideImpressionRecording = false

        adChoicesContent = sampleAd.informationIcon
    }

    override fun recordImpression() {
        sampleAd.recordImpression()
    }

    override fun handleClick(view: View) {
        sampleAd.handleClick(view)
    }
}

下面我们来介绍一下构造函数方法及其执行的一些操作:

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

构造函数接受 SampleNativeAdNativeAdOptions 参数。 SampleNativeAd 是示例 SDK 用于其原生广告的原生广告类。映射器需要使用对参与中介的广告的引用,以便传递点击和展示事件。 NativeAdOptions 包含了发布商对原生广告的偏好设置。两个参数均存储为局部变量。

设置映射的素材资源属性

此映射器类会从其父级 UnifiedNativeAdMapper 继承一些应用安装广告所特有的素材资源属性。构造函数会从参与中介的广告中获取素材资源数据,然后用该数据来填充这些属性。例如,以下代码可获取参与中介的广告的价格数据,然后用该数据来设置映射器的同名属性:

Java

NumberFormat formatter = NumberFormat.getCurrencyInstance();
String priceString = formatter.format(sampleAd.getPrice());
setPrice(priceString);

Kotlin

val formatter = NumberFormat.getCurrencyInstance()
val priceString = formatter.format(sampleAd.price)
price = priceString

在本例中,参与中介的广告将价格存储为 double,而 AdMob 会为同一素材资源使用 String。映射器会负责处理这些类型的转化。

映射图片素材资源

与映射较为简单的数据类型(如 doubleString)相比,映射图片素材资源会稍微复杂一点。因为图片既可以自动下载,也可以仅作为网址值返回,而且其“像素与 dpi 的比例”还会变化。为了帮助自定义事件开发者管理这些详细信息,Google 移动广告 SDK 提供了 NativeAd.Image 类。与开发者需要创建 UnifiedNativeAdMapper 的子类来映射参与中介的原生广告的方式大致相同,他们还应该创建 NativeAd.Image 的子类,以帮助他们映射该类的图片素材资源。

以下代码中的 SampleUnifiedNativeAdMapper 使用了其映射的图片类来设置映射器的图标图片素材资源:

Java

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

Kotlin

icon = SampleNativeMappedImage(sampleAd.appIcon, sampleAd.appIconUri,
        SampleCustomEvent.SAMPLE_SDK_IMAGE_SCALE)

下面是自定义事件的 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;
    }
}

Kotlin

class SampleNativeMappedImage(private val drawable: Drawable,
                              private val imageUri: Uri,
                              private val scale: Double) : NativeAd.Image() {

    override fun getDrawable(): Drawable {
        return drawable
    }

    override fun getUri(): Uri {
        return imageUri
    }

    override fun getScale(): Double {
        return scale
    }
}

在本例中,映射的图片类仅提供一个简便的结构来保留图片及其元数据。但是,您自定义事件的映射的图片类可以包含转化所需的其他代码。

向额外信息 Bundle 添加其他字段

除了 AdMob 原生广告格式中的素材资源之外,一些参与中介的 SDK 可能还会提供额外的素材资源。NativeAdMapper 类包含一个名为 extrasBundle 属性,用于将这些素材资源传递给发布商。上述映射器将此用于示例 SDK 的“degree of awesomeness”素材资源:

Java

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

Kotlin

val extras = Bundle()
extras.putString(SampleCustomEvent.DEGREE_OF_AWESOMENESS, sampleAd.degreeOfAwesomeness)
this.extras = extras

Bundle 是键值对数据结构,因此应使用不同的键将多个素材资源纳入到一个 bundle 中。发布商可以使用 NativeAd 类的 getExtras() 方法来获取该数据。

广告选择

适配器负责通过 NativeAdMapper 界面上的 setAdChoicesContent() 方法来提供“广告选择”图标。

以下是 SampleUnifiedNativeAdMapper 中的一段代码,展示了如何提供“广告选择”图标:

Java

public SampleUnifiedNativeAdMapper(SampleNativeAd ad,
NativeAdOptions adOptions) {
    ...
    setAdChoicesContent(sampleAd.getInformationIcon());
}

Kotlin

init {
    ...
    adChoicesContent = sampleAd.informationIcon
}

展示和点击事件

无论何时发生展示或点击,参与中介的 SDK 都必须得到通知,这一点很重要。因此 Google 移动广告 SDK 会帮助自定义事件开发者报告这些事件。有两种不同做法可供自定义事件选用,具体取决于参与中介的广告联盟 SDK 的需求。

使用 handleClick 和 recordImpression 处理点击和展示

如果参与中介的原生广告对象提供了记录点击和展示的方法,则自定义事件的映射器类可以使用这些方法。这是最常见的做法。NativeAdMapper 包含了 recordImpression()handleClick() 两种方法,自定义事件应替换和使用这些方法,以调用参与中介的原生广告对象上的相应方法。

SampleUnifiedNativeAdMapper 的处理方式如下所示:

Java

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

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

Kotlin

override fun recordImpression() {
    sampleAd.recordImpression()
}

override fun handleClick(view: View) {
    sampleAd.handleClick(view)
}

SampleUnifiedNativeAdMapper 保留了对示例 SDK 的原生广告对象的引用,因此可轻松调用该对象上的相应方法来报告点击或展示。请注意,handleClick() 方法的唯一参数是与收到点击的原生广告素材资源相对应的 View 对象。

替换默认的点击处理和展示记录方法

一些参与中介的 SDK 可能偏好自行跟踪点击和展示。在这种情况下,您应在 NativeAdMapper 的构造函数中执行以下两项调用来替换默认的点击和展示跟踪方法:

Java

setOverrideClickHandling(true);
setOverrideImpressionRecording(true);

Kotlin

setOverrideClickHandling(true)
setOverrideImpressionRecording(true)

将事件转发至移动广告 SDK 中所述,自行跟踪点击和展示的自定义事件需通过 onAdClicked() 方法和 onAdImpression() 方法将点击和展示报告给 Google 移动广告 SDK。

您还应替换 trackView() 方法,然后使用它将原生广告的视图传递给参与中介的 SDK 的原生广告对象,以便参与中介的 SDK 可以将其用于跟踪。本指南的代码段均来自我们的自定义事件示例项目,但其中的示例 SDK 并不使用这种做法。如要使用这种做法,则自定义事件代码可能如下所示:

Java

public void trackView(View view) {
    sampleAd.setNativeAdViewForTracking(view);
}

Kotlin

override fun trackView(View view) {
    sampleAd.setNativeAdViewForTracking(view)
}

NativeAdMapper 也提供了相应的 untrackView() 方法,自定义事件在执行与跟踪相反的操作(即释放对视图的所有引用并解除它与原生广告对象之间的关联)时,应改为使用此方法。

使用自定义事件

要使用自定义事件,您需要将其添加至广告单元的中介配置。 这可在 AdMob 界面中完成。(有关修改广告单元的中介配置的详细说明,请查阅创建自定义事件。)

在将自定义事件添加至广告单元的中介配置时,系统会要求您提供三项信息:

  • Class Name - 这是您的自定义事件的类名称,包含完整的软件包名称。
  • Label - 这是您希望 AdMob 的界面在展示广告单元的中介来源时用于代表自定义事件的标签。它是您的专属标签,因为它仅会显示在 AdMob.com 上。
  • Parameter - 这是一个字符串值,每当针对该广告单元发出请求时,系统就会将其传递给相应的自定义事件。通常情况下,此字符串值会设置为参与中介的广告联盟提供的广告单元 ID。

以下是示例自定义事件条目的屏幕截图:

大功告成!至此,您已学习了为 AdMob 编写您自己的 Android 自定义事件所需的全部内容。

发送以下问题的反馈:

此网页
Google AdMob > 移动广告 SDK > Android
Google AdMob > 移动广告 SDK > Android
需要帮助?请访问我们的支持页面