You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native AdMob插屏广告仅展示一次 报Ad is already loaded错误

问题现象
  • 运行时报错:AdMobInterstitial [Unhandled promise rejection: Error: Ad is already loaded.]
  • 实际表现:插屏广告仅首次可以正常弹出,用户关闭广告后再次触发展示逻辑时广告无响应,必须重启应用才能再次展示
  • 错误截图:AdMob广告加载报错截图
核心原因
  1. 依赖严重冲突:当前项目同时安装了6个功能完全重叠的AdMob广告SDK,分别是@react-native-admob/admob、@react-native-firebase/admob、expo-ads-admob、react-native-admob、react-native-admob-ads、react-native-google-mobile-ads,另外还装了react-native-ad-manager广告管理包。多个独立的SDK会同时操作广告实例、监听广告生命周期事件,实例状态标记互相覆盖:广告关闭后部分SDK判定实例已销毁需重新加载,另一部分SDK判定实例仍处于已加载状态,此时调用加载接口就会触发「广告已加载」报错,同时阻塞广告展示逻辑。
  2. 广告生命周期逻辑错误:插屏广告属于单次消耗型资源,广告展示完成后旧实例会自动回收,必须重新加载新的广告资源才能再次展示。绝大多数出现该问题的场景,都是没有在广告关闭的回调中触发下一轮广告预加载,同时没有在调用加载接口前判断广告当前状态,重复触发加载动作。
  3. 异步调用未做异常捕获:广告加载、展示的Promise接口没有加try/catch兜底,导致状态异常时直接抛出未处理的Promise rejection。
修复步骤

第一步:清理冗余依赖

只保留1个和项目技术栈匹配的官方维护AdMob SDK即可,当前是Expo 45项目,直接保留内置的expo-ads-admob即可,其余所有AdMob相关包全部卸载:

yarn remove @react-native-admob/admob @react-native-firebase/admob react-native-admob react-native-admob-ads react-native-google-mobile-ads react-native-ad-manager

卸载完成后重新安装依赖、重启打包服务,清除缓存后重新编译应用。

第二步:修正插屏广告调用逻辑

按照插屏广告的生命周期规范实现加载、展示逻辑,核心要点是:广告关闭后自动预加载下一条、调用加载/展示接口前先判断当前广告状态、所有异步操作加异常捕获。
参考实现(React Hook封装):

import { AdMobInterstitial } from 'expo-ads-admob';
import { useEffect, useCallback, Platform } from 'react-native';

// 测试阶段请替换为AdMob官方测试插屏广告ID,上线前替换为自己的正式广告ID
const INTERSTITIAL_UNIT_ID = Platform.select({
  android: 'ca-app-pub-3940256099942544/1033173712',
  ios: 'ca-app-pub-3940256099942544/4411468910',
});

export default function useInterstitial() {
  const loadInterstitial = useCallback(async () => {
    try {
      AdMobInterstitial.setAdUnitID(INTERSTITIAL_UNIT_ID);
      // 先判断广告是否已经加载完成,避免重复调用加载接口
      const isReady = await AdMobInterstitial.getIsReadyAsync();
      if (!isReady) {
        await AdMobInterstitial.requestAdAsync({
          servePersonalizedAds: true,
        });
      }
    } catch (err) {
      console.log('插屏广告加载异常:', err);
    }
  }, []);

  const showInterstitial = useCallback(async () => {
    try {
      const isReady = await AdMobInterstitial.getIsReadyAsync();
      if (isReady) {
        await AdMobInterstitial.showAdAsync();
      } else {
        // 广告未就绪时先触发预加载,等下一次触发时机再展示
        loadInterstitial();
      }
    } catch (err) {
      console.log('插屏广告展示异常:', err);
    }
  }, [loadInterstitial]);

  useEffect(() => {
    // 组件挂载时首次预加载广告
    loadInterstitial();
    // 监听广告关闭事件,广告关闭后立刻预加载下一条
    const closeSub = AdMobInterstitial.addListener(
      'interstitialDidClose',
      loadInterstitial
    );
    // 监听广告加载失败事件,失败后延迟重试
    const failSub = AdMobInterstitial.addListener(
      'interstitialDidFailToLoad',
      () => {
        setTimeout(loadInterstitial, 3000);
      }
    );

    return () => {
      closeSub.remove();
      failSub.remove();
    };
  }, [loadInterstitial]);

  return { showInterstitial };
}

业务页面中调用时,直接引入hook拿到showInterstitial方法,在需要触发广告的时机(比如通关、页面切换、任务完成)直接调用即可,不需要手动处理加载逻辑。

注意事项

  • 测试阶段严禁使用正式广告ID频繁请求、展示广告,否则会触发AdMob账号风控,导致广告无法加载、账号被封禁。
  • 不要在应用启动、页面刚加载时立刻弹出插屏广告,会违反AdMob政策导致应用被下架。
  • 如果清理依赖后仍然存在冲突,可以删除node_modules、yarn.lock/package-lock.json后重新安装依赖,同时清除Expo/Metro打包缓存。

内容的提问来源于stack exchange,提问作者The.Kingslayer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:09:20