skip to Main Content

I am using google_mobile_ads Flutter package (version ^3.0.0) in a Flutter app targeting Android. I am occasionally getting ANRs that could be related to ads.

This article talks about optimizing Google mobile ads initialization and loading on Android as a way to prevent ANRs.

Should I add these options to my Android manifest considering I am using Flutter and not a native Android app that the article is targeting?

<manifest>
  ...
  <application>
      ...
      <meta-data
          android:name="com.google.android.gms.ads.flag.OPTIMIZE_INITIALIZATION"
          android:value="true"/>
     <meta-data
          android:name="com.google.android.gms.ads.flag.OPTIMIZE_AD_LOADING"
          android:value="true"/>

  </application>
</manifest>

2

Answers


  1. One way of doing this is with the variable isBannerLoaded along with the BannerAdListener.

    import 'dart:developer';
    
    import 'package:flutter/material.dart';
    import 'package:google_mobile_ads/google_mobile_ads.dart';
    import 'package:provider/provider.dart';
    
    class AdBanner extends StatefulWidget {
      final String adUnitId;
      final AdSize size;
      const AdBanner({this.adUnitId, this.size});
    
      @override
      State<AdBanner> createState() => _AdBannerState();
    
      static AdSize getBannerSize() {
        final width =
            MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.width;
        final height =
            MediaQueryData.fromWindow(WidgetsBinding.instance.window).size.height;
        if ((width >= 460 && width <= 500) || (height >= 800 && height <= 900)) {
          return AdSize(width: 336, height: 280);
        } else if ((width >= 360 && width <= 375) ||
            (height >= 600 && height <= 700)) {
          return AdSize(width: 320, height: 100);
        } else if ((width >= 375 && width <= 414) ||
            (height >= 700 && height <= 800)) {
          return AdSize(width: 300, height: 250);
        } else if ((width >= 300 && width <= 360) ||
            (height >= 400 && height <= 600)) {
          return AdSize(width: 320, height: 50);
        } else {
          return AdSize(width: 320, height: 50);
        }
      }
    }
    
    class _AdBannerState extends State<AdBanner> {
      bool isBannerLoaded = false;
      BannerAd myBanner;
      @override
      Widget build(BuildContext context) {
        print('AdBanner build : ' + widget.adUnitId);
       
        final BannerAd bannerAd = myBanner;
        if (isBannerLoaded && bannerAd != null) {
          return Container(
              height: bannerAd.size.height.toDouble(),
              width: bannerAd.size.width.toDouble(),
              child: AdWidget(ad: bannerAd));
        } else {
          return Container(
          );
        }
    
       
      }
    
      @override
      void didChangeDependencies() {
        super.didChangeDependencies();
        myBanner = BannerAd(
          adUnitId: widget.adUnitId ?? '/234721286/NY_KB_Home_Micrec_23',
          size: widget.size ?? AdSize.banner,
          request: AdRequest(),
          listener: BannerAdListener(
            onAdLoaded: (Ad ad) {
              print('AdBanner onAdLoaded : ' + ad.adUnitId);
              setState(() {
                isBannerLoaded = true;
              });
            },
            // Called when an ad request failed.
            onAdFailedToLoad: (Ad ad, LoadAdError error) {
              print('inside failed');
              // Dispose the ad here to free resources.
              ad.dispose();
              print('failed to load: $error');
            },
            // Called when an ad opens an overlay that covers the screen.
            onAdOpened: (Ad ad) => print('Ad opened.'),
            // Called when an ad removes an overlay that covers the screen.
            onAdClosed: (Ad ad) => print('Ad closed.'),
            // Called when an impression occurs on the ad.
            onAdImpression: (Ad ad) => print('Ad impression.'),
          ),
        )..load();
      }
    
      @override
      void dispose() {
        super.dispose();
        myBanner.dispose();
      }
    }
    
    Login or Signup to reply.
  2. Considering google_mobile_ads Flutter package does use the Google Mobile Ads SDK for Android, those optimizations should apply.

    Is there a downside to using this? Why is this not on by default if it just makes loading better without any potential "side-effects"?

    As described here, activating those optimizations means the initialization and ad loading tasks that require extended processing time are offloaded to background threads.

    This thread does not mention any drawback, and refer to this "Get started" guide.
    That means it is not the default only because those optimizations are still in Beta.

    The new testing features for ad inspector announced yesterday can help you validate those optimizations effects.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search