D. Joe
D. Joe

Reputation: 793

Admob banner not showing unless I put a breakpoint in the initState() function

I tried following the AdMob tutorial

https://codelabs.developers.google.com/codelabs/admob-ads-in-flutter#6

but I can't seem to get the ad banner to work properly.

With the code the way it's currently set, the banner doesn't show up at all. However, if I set a breakpoint at the line "_bannerAd.load();", the ad loads and the banner is displayed.

I can't figure out why, so any help would be greatly appreciated.

Thanks.

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:myapp/ad_helper_test.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'MyApp',
        theme: ThemeData(
            primarySwatch: Colors.blue,
        ),
        home: const MyAppHomePage(title: 'MyApp'),
    );
  }
}

class MyAppHomePage extends StatefulWidget {
  const MyAppHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyAppHomePage> createState() => _MyAppHomePageState();
}

class _MyAppHomePageState extends State<MyAppHomePage> {
    late BannerAd _bannerAd;
    bool _isBannerAdReady = false;

    @override
    void initState() {
        super.initState();
        _bannerAd = BannerAd(
            adUnitId: AdHelper.bannerAdUnitId,
            request: const AdRequest(),
            size: AdSize.banner,
            listener: BannerAdListener(
                onAdLoaded: (_) {
                    setState(() {
                        _isBannerAdReady = true;
                    });
                },
                onAdFailedToLoad: (ad, err) {
                    print('Failed to load a banner ad: ${err.message}');
                    _isBannerAdReady = false;
                    ad.dispose();
                },
            ),
        );

        _bannerAd.load();
    }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
              buildAdWidget()
          ],
        ),
      ),
    );
  }

    FutureBuilder<void> buildAdWidget() {
      return FutureBuilder<void>(
          future: _initGoogleMobileAds(),
          builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
              return Center(
                  child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                          if (_isBannerAdReady)
                              Align(
                                  alignment: Alignment.topCenter,
                                  child: SizedBox(
                                      width: _bannerAd.size.width.toDouble(),
                                      height: _bannerAd.size.height.toDouble(),
                                      child: AdWidget(ad: _bannerAd),
                                  ),
                              ),
                              
                          const Text("Here goes the rest of the app"),
                      ],
                  ),
              );
          },
      );
    }



    Future<InitializationStatus> _initGoogleMobileAds() {
        return MobileAds.instance.initialize();
    }

    @override
    void dispose() {
      super.dispose();
      _bannerAd.dispose();
    }
}

Upvotes: 0

Views: 610

Answers (1)

Nico Spencer
Nico Spencer

Reputation: 1181

Based on the documentation you need to initialize the framework MobileAds.instance.initialize(); before loading a banner. You are doing the opposite. Consider wrapping your homepage with a FutureBuilder that initializes the framework and renders your homepage when it is initialized otherwise returns some loading page.

In the tutorial they're handling this with routes. Which is probably a fair way to go.

edit

This is not tested but it should look something like this:

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:myapp/ad_helper_test.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'MyApp',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const DependencyLoader(),
    );
  }
}

class DependencyLoader extends StatelessWidget {
  const DependencyLoader({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: MobileAds.instance.initialize(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          MyAppHomePage(
            title: 'MyApp',
          );
        } else {
          /// Create a loading page of some sort
        }
      },
    );
  }
}

class MyAppHomePage extends StatefulWidget {
  const MyAppHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyAppHomePage> createState() => _MyAppHomePageState();
}

class _MyAppHomePageState extends State<MyAppHomePage> {
  late BannerAd _bannerAd;
  bool _isBannerAdReady = false;

  @override
  void initState() {
    super.initState();
    _bannerAd = BannerAd(
      adUnitId: AdHelper.bannerAdUnitId,
      request: const AdRequest(),
      size: AdSize.banner,
      listener: BannerAdListener(
        onAdLoaded: (_) {
          setState(() {
            _isBannerAdReady = true;
          });
        },
        onAdFailedToLoad: (ad, err) {
          print('Failed to load a banner ad: ${err.message}');
          _isBannerAdReady = false;
          ad.dispose();
        },
      ),
    );

    _bannerAd.load();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[buildAdWidget()],
        ),
      ),
    );
  }

  Widget buildAdWidget() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (_isBannerAdReady)
            Align(
              alignment: Alignment.topCenter,
              child: SizedBox(
                width: _bannerAd.size.width.toDouble(),
                height: _bannerAd.size.height.toDouble(),
                child: AdWidget(ad: _bannerAd),
              ),
            ),
          const Text("Here goes the rest of the app"),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _bannerAd.dispose();
  }
}

Upvotes: 1

Related Questions