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

Flutter集成AdMob测试横幅广告加载失败求助(错误码0)

Flutter AdMob测试横幅广告加载失败(错误码0)排查方案

问题描述

我正尝试按照YouTube教程《Flutter AdMob》集成测试横幅广告,代码无语法错误,但出现以下加载失败日志:
I/Ads (30634): Ad failed to load : 0
I/flutter (30634): Ad with id 0 is not available for onAdFailedToLoad.
已多次检查AdMobService、main.dart、SearchScreen及AndroidManifest中的代码,仍未找到问题所在。目前仅针对Android平台开发,恳请协助排查。

提供的相关代码

AdMob Service

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

class AdMobService {
  static String? get bannerAdUnitId {
    if (Platform.isAndroid) {
      return 'ca-app-pub-3940256099942544/6300978111';
    }
    return null;
  }

  static String? get interstitialAdUnitId {
    if (Platform.isAndroid) {
      return 'ca-app-pub-3940256099942544/1033173712';
    }
    return null;
  }

  static final BannerAdListener bannerListener = BannerAdListener(
    onAdLoaded: (ad) => debugPrint('Ad Loaded'),
    onAdFailedToLoad: (ad, error) {
      ad.dispose();
      debugPrint('Ad failed to load $error');
    },
    onAdOpened: (ad) => debugPrint('Ad opened'),
    onAdClosed: (ad) => debugPrint('Ad closed'),
  );
}

main.dart

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  MobileAds.instance.initialize();
  await Firebase.initializeApp();
}

SearchScreen(广告实现页面)

class SearchScreen extends StatefulWidget {
  const SearchScreen({Key? key}) : super(key: key);

  @override
  State<SearchScreen> createState() => _SearchScreenState();
}

class _SearchScreenState extends State<SearchScreen> {
  final TextEditingController searchController = TextEditingController();
  bool isShowUsers = false;
  BannerAd? _banner;

  @override
  void initState() {
    super.initState();
    _createBannerAd();
  }

  void _createBannerAd() {
    _banner = BannerAd(
      size: AdSize.fullBanner,
      adUnitId: AdMobService.bannerAdUnitId!,
      listener: AdMobService.bannerListener,
      request: const AdRequest(),
    )..load();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      bottomNavigationBar: _banner == null
          ? Container()
          : Container(
        margin: EdgeInsets.only(bottom: 12),
        height: 52,
        child: AdWidget(ad: _banner!),
      ),
      drawer: const DrawerWidget(),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 40),
            child: Container(
              decoration: BoxDecoration(
                color: lightBlueColor,
                borderRadius: BorderRadius.circular(8),
              ),
              padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 4),
              child: Row(
                children: [
                  const Image(
                    image: AssetImage('icons/search.png'),
                    width: 18,
                    color: kPrimaryColor,
                  ),
                  const SizedBox(width: 20),
                  Expanded(
                    child: TextField(
                      controller: searchController,
                      style: const TextStyle(
                          color: kPrimaryColor, fontFamily: 'Sen'),
                      decoration: const InputDecoration(
                        hintText: 'Search',
                        hintStyle:
                        TextStyle(color: Colors.black45, fontFamily: 'Sen'),
                        border: InputBorder.none,
                      ),
                      onSubmitted: (String value) {
                        setState(() {
                          isShowUsers = true;
                        });
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

Android Manifest

<meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3419835294" />

排查与解决步骤

1. 修正初始化顺序与异步等待

AdMob初始化是异步操作,当前代码未等待其完成就继续执行,且顺序在Firebase初始化之前。调整main.dart:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  // 等待AdMob初始化完成
  await MobileAds.instance.initialize();
}

2. 延迟广告加载时机

initState中直接创建广告可能遇到AdMob未初始化完成的情况,添加延迟:

@override
void initState() {
  super.initState();
  // 延迟1秒确保AdMob初始化完成后再加载广告
  Future.delayed(const Duration(seconds: 1), () {
    _createBannerAd();
  });
}

3. 优化错误日志获取详细信息

当前错误日志过于简略,修改BannerAdListener打印完整错误信息:

static final BannerAdListener bannerListener = BannerAdListener(
  onAdLoaded: (ad) => debugPrint('Ad Loaded'),
  onAdFailedToLoad: (ad, error) {
    ad.dispose();
    // 打印错误码和详细描述,便于定位问题
    debugPrint('Ad加载失败:错误码${error.code},描述${error.message}');
  },
  onAdOpened: (ad) => debugPrint('Ad opened'),
  onAdClosed: (ad) => debugPrint('Ad closed'),
);

4. 重置广告状态并可选重试

广告加载失败后,_banner仍为非空状态,需更新状态并可尝试重新加载:

onAdFailedToLoad: (ad, error) {
  ad.dispose();
  debugPrint('Ad加载失败:错误码${error.code},描述${error.message}');
  setState(() {
    _banner = null;
    // 可选:延迟3秒后重新尝试加载
    // Future.delayed(const Duration(seconds: 3), () => _createBannerAd());
  });
}

5. 测试环境验证

  • 确认使用的测试APP ID和横幅ID均为Google官方提供的测试ID(当前配置是正确的)
  • 切换网络环境(比如从WiFi换为移动数据),部分网络可能限制测试广告请求
  • 重启测试设备,避免设备被临时限制

内容的提问来源于stack exchange,提问作者Ariana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:17:57