设置开屏广告

开屏广告会在用户打开或返回您的应用时展示。用户可以随时关闭开屏广告。如需通过应用加载界面创收,请使用开屏广告。如需了解详情,请参阅开屏广告指南和最佳实践。

本指南介绍了如何将开屏广告植入到 React Native 原生应用中。

前提条件

在继续操作之前,请确保满足以下条件:

Android

ca-app-pub-3940256099942544/9257395921

iOS

ca-app-pub-3940256099942544/5575463023

了解广告预加载

Google Mobile Ads SDK for React Native 中的广告预加载功能可自动加载和缓存广告。

广告预加载具有以下优势:

  • 引用管理:在广告展示之前,保留对广告的引用。
  • 自动重新加载:从缓存中检索到广告后,加载新广告。
  • 代管式重试:在广告加载失败时加载新广告。
  • 过期处理:在广告过期前刷新广告。
  • 缓存优化:优化缓存顺序,以投放优先级最高的广告。

如需手动加载广告,请参阅加载单个开屏广告指南。

开始预加载

如需开始预加载广告,请调用 AppOpenAdPreloader.start 方法,并传递 preloadId 值、配置设置和事件回调,以监控缓冲区状态变化:

export function startAppOpenAdPreloader(
  adUnitId: string,
  preloadId: string,
  customPreloadCallback?: PreloadCallback,
): boolean {
  const started = AppOpenAdPreloader.start(
    preloadId,
    {
      request: {adUnitId},
      bufferSize: 2,
    },
    {
      // Called when an ad is preloaded into the buffer.
      onAdPreloaded: (event) => {
        console.log(`App open ad preloaded for ${event.preloadId}`);
        customPreloadCallback?.onAdPreloaded?.(event);
      },
      // Called when an ad fails to preload.
      onAdFailedToPreload: (error: LoadAdError) => {
        console.error('Failed to preload app open ad:', error.message);
        customPreloadCallback?.onAdFailedToPreload?.(error);
      },
      // Called when all preloaded ads in the buffer have been shown.
      onAdsExhausted: () => {
        console.log('App open ad buffer exhausted.');
        customPreloadCallback?.onAdsExhausted?.();
      },
    },
  );
  return started;
}

preloadId 是一个字符串,用于唯一标识广告预加载配置。如果 adUnitId 仅用于应用中的单个预加载配置,则可以使用该广告单元 ID 作为预加载 ID。如果您的应用需要为同一广告单元 ID 使用多个预加载器,请为每个预加载 ID 传递不同的字符串。

当应用从缓冲区轮询预加载的广告时,Google Mobile Ads SDK for React Native 会在后台请求替换广告,以重新填充缓冲区。如果缓冲区中没有预加载的广告,Google Mobile Ads SDK for React Native 会调用 onAdsExhausted 回调。

预加载缓存限制

Google Mobile Ads SDK for React Native 会在应用范围内强制限制预加载广告的总数:

  • 默认限制:Google 最多在内存中保留 6 个预加载的广告。
  • 我们建议为每个预加载 ID 保留两个缓冲区空间。

如果您的应用达到应用级上限,系统会暂停针对预加载广告的后台请求,直到现有广告被轮询并展示或销毁。

轮询并展示广告

如需检查是否有可用的预加载广告并检索广告实例,请调用 AppOpenAdPreloader.pollAd 方法。

如需监听全屏展示事件,请在调用 show 方法之前,在返回的 AppOpenAd 实例的 adEventCallback 属性上注册回调:

export function showPreloadedAppOpenAd(
  preloadId: string,
  customAdEventCallback?: FullScreenAdEventCallback,
) {
  if (!AppOpenAdPreloader.isAdAvailable(preloadId)) {
    console.log('No preloaded app open ad available right now.');
    return;
  }

  const ad = AppOpenAdPreloader.pollAd(preloadId);
  if (!ad) {
    return;
  }

  ad.adEventCallback = {
    // Called when the ad is presented on screen.
    onAdShowedFullScreenContent: () => {
      console.log('Preloaded app open ad showed full screen content.');
      customAdEventCallback?.onAdShowedFullScreenContent?.();
    },
    // Called when the ad is closed by the user.
    onAdDismissedFullScreenContent: () => {
      console.log('Preloaded app open ad dismissed full screen content.');
      customAdEventCallback?.onAdDismissedFullScreenContent?.();
      ad.destroy();
    },
    // Called when presentation fails.
    onAdFailedToShowFullScreenContent: (error) => {
      console.error('Failed to show preloaded app open ad:', error);
      customAdEventCallback?.onAdFailedToShowFullScreenContent?.(error);
      ad.destroy();
    },
    // Called when an impression is recorded.
    onAdImpression: () => {
      console.log('Preloaded app open ad recorded an impression.');
      customAdEventCallback?.onAdImpression?.();
    },
    // Called when the user taps the ad.
    onAdClicked: () => {
      console.log('Preloaded app open ad was clicked.');
      customAdEventCallback?.onAdClicked?.();
    },
    // Called when the ad is estimated to have earned money.
    onAdPaid: (adValue) => {
      console.log(
        `Preloaded app open ad paid: ${adValue.amountMicros}` +
          ` ${adValue.currencyCode}`,
      );
      customAdEventCallback?.onAdPaid?.(adValue);
    },
  };

  ad.show();
}

如需释放内存和资源,请在用户关闭广告或广告未能展示时,在 onAdDismissedFullScreenContent 和 onAdFailedToShowFullScreenContent 回调中调用 ad.destroy 方法。

查看回答信息

如需检查下一个预加载广告的详细信息,而不从缓存中移除该广告,请调用 AppOpenAdPreloader.peekAdResponseInfo 方法:

export function peekAppOpenAdResponseInfo(
  preloadId: string,
): ResponseInfo | null {
  const responseInfo = AppOpenAdPreloader.peekAdResponseInfo(preloadId);
  if (responseInfo) {
    console.log('Next preloaded app open ad response info:', responseInfo);
  }
  return responseInfo;
}

使用应用级管理器管理开屏广告

由于开屏广告会在应用启动和前台转换期间全局展示,因此我们建议您在 React 组件树之外的应用级管理器中管理预加载器生命周期状态。

使用应用级管理器具有以下几项关键优势:

  • 使预加载器状态独立于各个屏幕导航和组件生命周期。
  • 在整个应用中,将广告事件回调、状态跟踪和清理集中在单个共享实例中。
  • 控制何时监听进入前台事件,防止在广告关闭时重复展示。

以下示例使用 AppOpenAdPreloader 对象实现应用级管理器:

export class AppOpenAdManager {
  private adUnitId: string;
  private preloadId: string;
  private appStateSubscription?: NativeEventSubscription;
  private startTimeoutId?: ReturnType<typeof setTimeout>;

  constructor(adUnitId: string, preloadId: string) {
    this.adUnitId = adUnitId;
    this.preloadId = preloadId;
  }

  start(): boolean {
    if (!AppOpenAdPreloader.getConfiguration(this.preloadId)) {
      AppOpenAdPreloader.start(
        this.preloadId,
        {
          request: {adUnitId: this.adUnitId},
          bufferSize: 2,
        },
        {
          onAdPreloaded: (event) => {
            console.log(`App open ad preloaded for ${event.preloadId}`);
          },
          onAdFailedToPreload: (error: LoadAdError) => {
            console.error('Failed to preload app open ad:', error.message);
          },
          onAdsExhausted: () => {
            console.log('App open ad buffer exhausted.');
          },
        },
      );
    }

    if (!this.appStateSubscription && !this.startTimeoutId) {
      // Delay attaching the listener to ensure native dismissal transitions complete
      this.startTimeoutId = setTimeout(() => {
        this.startTimeoutId = undefined;
        if (!this.appStateSubscription) {
          this.appStateSubscription = AppState.addEventListener(
            'change',
            (nextAppState: AppStateStatus) => {
              if (nextAppState === 'active') {
                this.showAdIfAvailable();
              }
            },
          );
        }
      }, APP_STATE_LISTENER_DELAY_MS);
    }

    return true;
  }

  pause(): void {
    if (this.startTimeoutId) {
      clearTimeout(this.startTimeoutId);
      this.startTimeoutId = undefined;
    }
    this.appStateSubscription?.remove();
    this.appStateSubscription = undefined;
  }

  stop(): void {
    this.pause();
    AppOpenAdPreloader.destroy(this.preloadId);
  }

  showAdIfAvailable() {
    if (!AppOpenAdPreloader.isAdAvailable(this.preloadId)) {
      console.log('App open ad is not preloaded or available right now.');
      return;
    }

    const ad = AppOpenAdPreloader.pollAd(this.preloadId);
    if (!ad) {
      return;
    }

    // Pause listener while presenting the ad
    this.pause();

    ad.adEventCallback = {
      onAdShowedFullScreenContent: () => {
        console.log('Preloaded app open ad showed full screen content.');
      },
      onAdDismissedFullScreenContent: () => {
        console.log('Preloaded app open ad dismissed full screen content.');
        ad.destroy();
        this.start();
      },
      onAdFailedToShowFullScreenContent: (error) => {
        console.error('Failed to show preloaded app open ad:', error);
        ad.destroy();
        this.start();
      },
    };

    ad.show();
  }
}

监听应用进入前台事件

如需在应用返回前台时展示广告,请在应用的根组件(例如 App.tsx)中,在 AppState 模块上注册 change 监听器。检查状态何时转换为 active。例如,在 App.tsx 组件中对广告管理器实例调用 start 方法。

呈现广告信息叠加层或着陆页(例如展示全屏广告或点按横幅广告)会将您的应用推送到后台。当用户返回您的应用时,应用会收到新的 active 状态事件。为防止出现意外的广告展示或循环(即从广告返回时展示缓存中的开屏广告),请执行以下操作:

  1. 在展示全屏广告之前,请先移除 AppState 事件监听器。
  2. 为确保无论用户关闭广告还是广告未能展示,监听都会恢复,请在 onAdDismissedFullScreenContent 和 onAdFailedToShowFullScreenContent 回调中再次添加 AppState 事件监听器。

如需查看控制前台事件监听器何时暂停和恢复的完整示例,请参阅 AppOpenAdManager 实现。

了解冷启动和加载屏幕

当应用从头开始启动时,就会发生冷启动,例如,用户首次打开应用时,或者设备关闭应用以释放内存后。在冷启动期间,您没有预先加载好的开屏广告可供接下来展示。

由于广告请求延迟,用户可能会在广告展示之前与您的应用互动。在冷启动时,仅在加载应用素材资源的加载屏幕中展示开屏广告。如果素材资源已加载完毕,并且用户在广告加载之前已看到主要内容,则不要展示广告。

清理资源

当某个屏幕或广告单元 ID 不再需要预加载时(例如,当离开预加载广告的屏幕时),请调用 AppOpenAdPreloader.destroy 方法来释放预加载器资源,并防止在内存中保留未使用的广告对象:

export function destroyAppOpenAdPreloader(preloadId: string) {
  AppOpenAdPreloader.destroy(preloadId);
}

除了销毁预加载器队列之外,请务必在用户关闭广告或广告未能展示时销毁各个轮询的广告实例。如需了解详情,请参阅轮询和展示广告。

查看完整示例

以下示例组件会在装载时开始预加载,跟踪可用的广告数量,并提供用于展示预加载的开屏广告的控件:

export function AppOpenScreen() {
  const [numAdsAvailable, setNumAdsAvailable] = useState<number>(0);
  const [status, setStatus] = useState<string>('Preloader idle.');

  const refreshAdCount = () => {
    const count = AppOpenAdPreloader.getNumAdsAvailable(PRELOAD_ID);
    setNumAdsAvailable(count);
  };

  useEffect(() => {
    // Start preloading ads on component mount
    const started = startAppOpenAdPreloader(APP_OPEN_AD_UNIT_ID, PRELOAD_ID, {
      onAdPreloaded: () => {
        refreshAdCount();
        setStatus('App open ad preloaded into buffer.');
      },
      onAdFailedToPreload: (error) => {
        setStatus(`Failed to preload app open ad: ${error.message}`);
      },
      onAdsExhausted: () => {
        refreshAdCount();
        setStatus('Preload buffer exhausted for app open ads.');
      },
    });
    if (started) {
      setStatus('Preloader started.');
    }

    // Clean up preloader resources on component unmount
    return () => {
      destroyAppOpenAdPreloader(PRELOAD_ID);
    };
  }, []);

  const handleShowAd = () => {
    setStatus('Showing preloaded ad...');
    showPreloadedAppOpenAd(PRELOAD_ID, {
      onAdDismissedFullScreenContent: () => {
        setStatus('Ad dismissed.');
      },
      onAdFailedToShowFullScreenContent: (error) => {
        setStatus(`Failed to show preloaded ad: ${error.message}`);
      },
    });
    refreshAdCount();
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Preload App Open Ads</Text>
      <Text style={styles.status}>Status: {status}</Text>
      <Text style={styles.status}>Ads Available: {numAdsAvailable}</Text>
      <View style={styles.buttonGroup}>
        <Button
          title="Show Preloaded Ad"
          onPress={handleShowAd}
          disabled={numAdsAvailable === 0}
        />
      </View>
    </View>
  );
}

替换以下内容:

  • 将 APP_OPEN_AD_UNIT_ID 替换为您的广告单元 ID。
  • 将 PRELOAD_ID 替换为您的预加载器 ID。

后续步骤

植入开屏广告后,请探索以下主题: