横幅广告和插页式广告的自定义事件

本指南适用于希望使用 AdMob 中介实现以下目标的发布商:

  • 展示 AdMob 界面不直接支持的广告联盟所提供的广告。
  • 展示自定义视图而非广告。

借助自定义事件,您可以编写自定义的中介适配器,从而在广告空间中放置任意视图。在本指南中,我们将介绍如何编写自定义事件,以通过我们开发的示例 SDK 请求广告。您可以在 GitHub 上找到自定义事件的完整源代码和相应的示例 SDK。

前提条件

在为横幅广告或插页式广告集成自定义事件之前,您需要将相应广告格式集成到自己的应用中,以下是相关指南:

在以下示例中,您将首先在 AdMob 中介内创建一个横幅广告自定义事件。这需要通过 AdMob 界面定义一个自定义事件,使之指向您应用中特定的类,然后实现 CustomEventBanner 以投放视图。此示例将定义一个自定义事件,用于展示来自该示例广告联盟的广告。

定义自定义事件

必须在 AdMob 界面中定义自定义事件。要创建自定义事件,请按照这些说明操作。

以下屏幕截图显示的是自定义事件示例的部分设置:

请求横幅广告

要请求横幅广告,请定义实现 CustomEventBanner 的类,并将其命名为 SampleCustomEventBanner。在选择了广告中介瀑布流中的自定义事件后,中介会根据您在设置中提供的类名称调用 requestBannerAd() 方法。

上面定义的可选参数作为 requestBannerAd() 方法的一部分传递到您的自定义事件中。通常,此参数是一个可使自定义事件确定要加载的广告的标识符。

您还应该根据需要实现生命周期方法。如果用户调用 AdView.pause()AdView.resume()、 方法,AdMob 中介将会向适配器转发 onPause()onResume() 活动事件。该示例广告联盟不包括暂停或恢复调用,因此它提供了一个空的实现方案。当适配器即将销毁时,中介会尽力尝试调用 onDestroy()。请在此时执行必要的清理操作。

下面是 SampleCustomEventBanner 的实现示例:

Java

public class SampleCustomEventBanner implements CustomEventBanner {

    /** The SampleAdView representing a banner ad. */
    private SampleAdView sampleAdView;

    /** The event is being destroyed. Perform any necessary cleanup here. */
    @Override
    public void onDestroy() {
        if (sampleAdView != null) {
            sampleAdView.destroy();
        }
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    @Override
    public void onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    @Override
    public void onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }

    @Override
    public void requestBannerAd(Context context,
            CustomEventBannerListener listener,
            String serverParameter,
            AdSize size,
            MediationAdRequest mediationAdRequest,
            Bundle customEventExtras) {

        sampleAdView = new SampleAdView(context);

        // Assumes that the serverParameter is the AdUnit for the Sample Network.
        sampleAdView.setAdUnit(serverParameter);

        sampleAdView.setSize(new SampleAdSize(size.getWidth(), size.getHeight()));

        // Implement a SampleAdListener and forward callbacks to AdMob.
        // The callback forwarding is handled by SampleBannerEventFowarder.
        sampleAdView.setAdListener(new SampleCustomBannerEventForwarder(listener, sampleAdView));

        // Make an ad request.
        sampleAdView.fetchAd(createSampleRequest(mediationAdRequest));

        }

    private SampleAdRequest createSampleRequest(MediationAdRequest mediationAdRequest) {
        SampleAdRequest request = new SampleAdRequest();
        request.setTestMode(mediationAdRequest.isTesting());
        request.setKeywords(mediationAdRequest.getKeywords());
        return request;
        }
}

Kotlin

class SampleCustomEventBanner : CustomEventBanner {

    /** The SampleAdView representing a banner ad. */
    private lateinit var mSampleAdView: SampleAdView

    /** The event is being destroyed. Perform any necessary cleanup here. */
    override fun onDestroy() {
        mSampleAdView.destroy()
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    override fun onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    override fun onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }

    override fun requestBannerAd(context: Context,
                                 listener: CustomEventBannerListener,
                                 serverParameter: String,
                                 size: AdSize,
                                 mediationAdRequest: MediationAdRequest,
                                 customEventExtras: Bundle?) {

        mSampleAdView = SampleAdView(context)

        // Assumes that the serverParameter is the AdUnit for the Sample Network.
        mSampleAdView.adUnit = serverParameter
        mSampleAdView.size = SampleAdSize(size.width, size.height)

        // Implement a SampleAdListener and forward callbacks to
        // AdMob mediation. The callback forwarding
        // is handled by SampleBannerEventFowarder.
        mSampleAdView.adListener = SampleCustomBannerEventForwarder(listener, mSampleAdView)

        // Make an ad request.
        mSampleAdView.fetchAd(createSampleRequest(mediationAdRequest))
    }

    private fun createSampleRequest(mediationAdRequest: MediationAdRequest): SampleAdRequest {
        val request = SampleAdRequest()
        request.testMode = mediationAdRequest.isTesting
        request.keywords = mediationAdRequest.keywords
        return request
    }
}

示例中使用的 SampleAdView 类是示例 SDK 中第三方广告视图的一个简单示例。

针对自定义事件请求发送广告联盟额外信息(可选)

如果您需要向自定义事件发送额外参数,请使用 AdRequest.Builder 类的 addCustomEventExtrasBundle() 方法。PublisherAdRequest.Builder 类的 您必须传入自定义事件适配器类以及自定义事件适配器所需的额外内容组合。

以下代码段说明了如何为之前定义的 SampleCustomEventBanner 类传递 SampleExtra 参数:

Bundle extras = new Bundle();
extras.putBoolean("SampleExtra", true);

AdRequest request = new AdRequest.Builder()
        .addCustomEventExtrasBundle(SampleCustomEventBanner.class, extras)
        .build();

针对某个自定义事件请求,如果没有使用正确的自定义事件类和组合调用 addCustomEventExtras(),则适配器接收的 bundle 参数将为 null

通知 AdMob 中介

当自定义事件加载广告时,无论成功或失败,均须通过 CustomEventBannerListener 接口通知中介。否则,自定义事件会超时,广告中介会继续联系下一个广告联盟。

为您的广告联盟实现广告监听器,并对 CustomEventBannerListener 进行相关回调以将消息发回给 AdMob 中介。

我们已经创建实现 SampleAdListener 接口的 SampleCustomBannerEventForwarder 类,用于转发来自示例广告联盟的回调。

AdMob 中介支持以下回调:

方法 调用时机
onAdLoaded() 横幅广告请求成功时。
onAdFailedToLoad() 横幅广告请求失败时。
onAdClicked() 用户点击横幅广告时。
onAdOpened() 横幅广告呈现全屏视图时。
onAdClosed() 用户点击横幅广告后返回应用时。
onAdLeftApplication() 横幅广告引起用户离开应用时。

插页式广告

方法 调用时机
onAdLoaded() 插页式广告请求成功时。
onAdFailedToLoad() 插页式广告请求失败时。
onAdClicked() 用户点击插页式广告时。
onAdOpened() 插页式广告向用户展示且呈现全屏视图时。
onAdClosed() 插页式广告关闭时。
onAdLeftApplication() 插页式广告引起用户离开应用时。

下面是一个 SampleCustomBannerEventForwarder 实现示例:

Java

public class SampleCustomBannerEventForwarder extends SampleAdListener {
    private CustomEventBannerListener mBannerListener;
    private SampleAdView mAdView;

    /**
     * Creates a new {@code SampleBannerEventForwarder}.
     * @param listener A {@link CustomEventBannerListener} that should receive
     *                 forwarded events.
     * @param adView   A {@link SampleAdView}.
     */
    public SampleCustomBannerEventForwarder(
            CustomEventBannerListener listener, SampleAdView adView) {
        this.mBannerListener = listener;
        this.mAdView = adView;
    }

    @Override
    public void onAdFetchSucceeded() {
        mBannerListener.onAdLoaded(mAdView);
    }

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

    @Override
    public void onAdFullScreen() {
        mBannerListener.onAdClicked();
        mBannerListener.onAdOpened();
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mBannerListener.onAdLeftApplication();
    }

    @Override
    public void onAdClosed() {
        mBannerListener.onAdClosed();
    }
}

Kotlin

class SampleCustomBannerEventForwarder(private val mBannerListener: CustomEventBannerListener,
                                       private val mAdView: SampleAdView) : SampleAdListener() {

    override fun onAdFetchSucceeded() {
        mBannerListener.onAdLoaded(mAdView)
    }

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

    override fun onAdFullScreen() {
        mBannerListener.onAdClicked()
        mBannerListener.onAdOpened()
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mBannerListener.onAdLeftApplication()
    }

    override fun onAdClosed() {
        mBannerListener.onAdClosed()
    }
}

插页式广告自定义事件

要实现插页式广告自定义事件,首先应在 AdMob 中介内创建一个插页式广告自定义事件,这与横幅广告自定义事件非常类似。然后,实现 CustomEventInterstitial 以便提供相关通知。与上文一样,此示例也使用该示例广告联盟。

定义自定义事件

您可以通过 AdMob 界面定义插页式广告自定义事件

请确保您为类名称指定的值具有完整路径。参数应该包含向您在自定义事件中实现的广告联盟发送广告请求所必需的全部信息。

请求插页式广告

要请求插页式广告,请定义一个实现 CustomEventInterstitial 的类;我们将这个类称为 SampleCustomEventInterstitial。在选择了中介广告瀑布流中的自定义事件后,中介会根据您在设置中提供的类名称调用 requestInterstitialAd() 方法。您可以使用此方法提供的参数向您所需的广告联盟发送插页式广告请求。以下示例显示了如何通过自定义事件从该示例广告联盟请求插页式广告:

下面是一个 SampleCustomEventInterstitial 实现示例:

Java

public class SampleCustomEventInterstitial implements CustomEventInterstitial {

    /** Represents a SampleInterstitial. */
    private SampleInterstitial sampleInterstitial;

    @Override
    public void requestInterstitialAd(Context context,
            CustomEventInterstitialListener listener,
            String serverParameter,
            MediationAdRequest mediationAdRequest,
            Bundle customEventExtras) {
        /**
         * In this method, you should:
         * 1. Create your interstitial ad.
         * 2. Set your ad network's listener.
         * 3. Make an ad request.
         */

        sampleInterstitial = new SampleInterstitial(context);

        // Here we're assuming the serverParameter is the ad unit for the sample ad network.
        sampleInterstitial.setAdUnit(serverParameter);

        // Implement a SampleAdListener and forward callbacks to
        // AdMob.
        sampleInterstitial.setAdListener(new SampleCustomInterstitialEventForwarder(listener));

        // Make an ad request.
        sampleInterstitial.fetchAd(createSampleRequest(mediationAdRequest));
    }

    /**
     * Helper method to create a SampleAdRequest.
     * @param mediationAdRequest The mediation request with targeting information.
     * @return The created SampleAdRequest.
     */
    private SampleAdRequest createSampleRequest(MediationAdRequest mediationAdRequest) {
        SampleAdRequest request = new SampleAdRequest();
        request.setTestMode(mediationAdRequest.isTesting());
        request.setKeywords(mediationAdRequest.getKeywords());
        return request;
    }

    @Override
    public void showInterstitial() {
        // Show your interstitial ad.
        sampleInterstitial.show();
    }

    /** The event is being destroyed. Perform any necessary cleanup here. */
    @Override
    public void onDestroy() {
        if (sampleInterstitial != null) {
            sampleInterstitial.destroy();
        }
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation
     * that the app is being paused.
     */
    @Override
    public void onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the
     * adapter if the developer notifies AdMob
     * mediation that the app is being resumed.
     */
    @Override
    public void onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }
}

Kotlin

class SampleCustomEventInterstitial : CustomEventInterstitial {

    /** Represents a SampleInterstitial.  */
    private lateinit var mSampleInterstitial: SampleInterstitial

    override fun requestInterstitialAd(context: Context,
                                       listener: CustomEventInterstitialListener,
                                       serverParameter: String,
                                       mediationAdRequest: MediationAdRequest,
                                       customEventExtras: Bundle?) {
        /**
         * In this method, you should:
         * 1. Create your interstitial ad.
         * 2. Set your ad network's listener.
         * 3. Make an ad request.
         */

        mSampleInterstitial = SampleInterstitial(context)

        // Here we're assuming the serverParameter is the ad unit for the sample ad network.
        mSampleInterstitial.adUnit = serverParameter

        // Implement a SampleAdListener and forward callbacks to
        // AdMob mediation.
        mSampleInterstitial.adListener = SampleCustomInterstitialEventForwarder(listener)

        // Make an ad request.
        mSampleInterstitial.fetchAd(createSampleRequest(mediationAdRequest))
    }

    /**
     * Helper method to create a [SampleAdRequest].
     * @param mediationAdRequest The mediation request with targeting information.
     * *
     * @return The created [SampleAdRequest].
     */
    private fun createSampleRequest(mediationAdRequest: MediationAdRequest): SampleAdRequest {
        val request = SampleAdRequest()
        request.testMode = mediationAdRequest.isTesting
        request.keywords = mediationAdRequest.keywords
        return request
    }

    override fun showInterstitial() {
        // Show your interstitial ad.
        mSampleInterstitial.show()
    }

    /** The event is being destroyed. Perform any necessary cleanup here. */
    override fun onDestroy() {
        mSampleInterstitial.destroy()
    }

    /**
     * The app is being paused. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being paused.
     */
    override fun onPause() {
        // The sample ad network doesn't have an onPause method, so does nothing.
    }

    /**
     * The app is being resumed. This call is only forwarded to the adapter if
     * the developer notifies AdMob mediation that
     * the app is being resumed.
     */
    override fun onResume() {
        // The sample ad network doesn't have an onResume method, so does nothing.
    }
}

插页式广告自定义事件接口要求您实现 showInterstitial() 方法。当您指示 Google 移动广告 SDK 展示插页式广告时,中介会调用此方法。

针对自定义事件请求发送广告联盟额外信息(可选)

如果您需要向自定义事件发送额外参数,请使用 AdRequest.Builder 类的 addCustomEventExtrasBundle() 方法。PublisherAdRequest.Builder 类的 您必须传入自定义事件适配器类以及自定义事件适配器所需的额外内容组合。

以下代码段说明了如何为之前定义的 SampleCustomEventInterstitial 类传递“SampleExtra”参数:

Bundle extras = new Bundle();
extras.putBoolean("SampleExtra", true);

AdRequest request = new AdRequest.Builder()
        .addCustomEventExtrasBundle(SampleCustomEventInterstitial.class, extras)
        .build();

针对某个自定义事件请求,如果没有使用正确的自定义事件类和组合调用 addCustomEventExtrasBundle(),则适配器接收的 bundle 参数将为 null

通知 AdMob 中介

与横幅广告自定义事件示例一样,您需要为广告联盟实现广告监听器以将消息发送回 AdMob 中介。

此示例 SampleCustomInterstitialEventForwarder 类实现 SampleAdListener 接口,可转发来自示例广告联盟的回调:

Java

public class SampleCustomInterstitialEventForwarder extends SampleAdListener {
    private CustomEventInterstitialListener mInterstitialListener;

    /**
     * Creates a new SampleInterstitialEventForwarder.
     * @param listener An AdMob CustomEventInterstitialListener that should
     *                 receive forwarded events.
     */
    public SampleCustomInterstitialEventForwarder(CustomEventInterstitialListener listener) {
        this.mInterstitialListener = listener;
    }

    @Override
    public void onAdFetchSucceeded() {
        mInterstitialListener.onAdLoaded();
    }

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

    @Override
    public void onAdFullScreen() {
        mInterstitialListener.onAdOpened();
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mInterstitialListener.onAdLeftApplication();
    }

    @Override
    public void onAdClosed() {
        mInterstitialListener.onAdClosed();
    }
}

Kotlin

class SampleCustomInterstitialEventForwarder(private val mInterstitialListener: CustomEventInterstitialListener)
        : SampleAdListener() {

    override fun onAdFetchSucceeded() {
        mInterstitialListener.onAdLoaded()
    }

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

    override fun onAdFullScreen() {
        mInterstitialListener.onAdOpened()
        // Only call onAdLeftApplication if your ad network actually exits the developer's app.
        mInterstitialListener.onAdLeftApplication()
    }

    override fun onAdClosed() {
        mInterstitialListener.onAdClosed()
    }
}

到这里,我们已经实现针对插页式广告的自定义事件。GitHub 上提供了完整的示例。 您可在已获支持的广告联盟上直接使用这些示例代码,也可在修改后用于展示自定义插页式广告。