6

I'm currently trying to display an admob banner in my app, However there are two pages where I would not like the banner displayed (For now i'm testing with just the settings route), And calling dispose on the banner does not hide it.

What I tried:

  1. Creating the banner for each widget and calling the dispose method inside the override of the widget's onDispose method
  2. Creating an Ad manager class that created the banner and saved a reference to it, and invoking a function from said class that calls dispose on the banner inside the init of the page I don't want the banner shown on.
  3. My current solution: an observer class that shows the banner on push, and if the name of the route matches what I'm looking for hides the banner.

So far none of these approaches have been successful :( What am I doing wrong? Am I missing something?

Observer class:

class AdmobObserver extends RouteObserver<PageRoute<dynamic>> {

  static ValueNotifier<bool> isBannerAdShowing = ValueNotifier<bool>(false);

  BannerAd _myBanner = BannerAd(
    adUnitId: AdManager.bannerAdUnitId,
    size: AdSize.banner,
    listener: (MobileAdEvent event) {
      if (event == MobileAdEvent.loaded) {
        isBannerAdShowing.value = true;
      }
      else if (event == MobileAdEvent.failedToLoad) {
        isBannerAdShowing.value = false;
      }
    },
  );

  @override
  void didPush(Route route, Route previousRoute) {
    super.didPush(route, previousRoute);
    if (route.settings.name == '/settings') {
      _myBanner?.dispose();
      isBannerAdShowing.value = false;
    } else {
      _showBannerAd();
    }
  }

  @override
  void didPop(Route route, Route previousRoute) {
    super.didPop(route, previousRoute);
    if (route.settings.name == '/settings') {
      _myBanner?.dispose();
      isBannerAdShowing.value = false;
    } else {
      _showBannerAd();
    }
  }

  void _showBannerAd() {
    _myBanner
      ..load()
      ..show();
  }
}

EDIT: I managed to get the observer to call dispose but now the banner either doesn't dispose or throws an exception: This exception occurs when I navigate from Home -> Settings -> Back to home (When the app is first built the banner disappears when I go to settings, but the error still occurs, but afterwards when I hot restart the same error occurs and the banner is still there, same error also happens when I pop into settings from a different page (Settings -> Page -> pop back to Settings)

 [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: 'package:firebase_admob/firebase_admob.dart': Failed assertion: line 249 pos 12: '_allAds[id] != null': is not true.
E/flutter (17108): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:42:39)
E/flutter (17108): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:38:5)
E/flutter (17108): #2      MobileAd.dispose (package:firebase_admob/firebase_admob.dart:249:12)
E/flutter (17108): #3      AdmobObserver.didPop (package:Switcheroo/AdManager.dart:87:18)
barbecu
  • 684
  • 10
  • 28
  • which plugin you are currently using? – Sachin Bhankhar Jun 27 '20 at 06:17
  • firebase_admob: ^0.9.3+2 – barbecu Jun 27 '20 at 08:59
  • I think it disposes when you leave first time and when you get back there is no ad so it's trying to dispose null value, what do you think ? ,maybe try to check if its null before disposing ?? – Henok Jun 28 '20 at 17:51
  • im using the question mark syntax so it shouldn't call dispose on a null object, And when I leave the first time the ad is still visible so I don't even think it disposed – barbecu Jun 28 '20 at 17:56
  • is the `route` name returned `route.settings.name` matching with the value being compared? Like any case sensitive error or minor typo ? – dev-aentgs Jun 30 '20 at 09:53
  • yeah it matches – barbecu Jun 30 '20 at 10:19
  • I think the `_allAds[id] != null` exception is thrown because the `_myBanner..load()` is not called. What happens if you do not call the `dispose` method and only keep `isBannerAdShowing.value = false;`? – dev-aentgs Jun 30 '20 at 17:43

2 Answers2

4

You need to dispose the banner like this

try {
      _myBanner?.dispose();
      _myBanner = null;
    } catch (ex) {
      log("banner dispose error");
    }
Koby 27
  • 1,049
  • 1
  • 8
  • 17
1

See here too, and the solution with the listener property on BannerAd. I still seem to need the catch block for the irritating error. Although at least this way the banner hides correctly.

https://github.com/flutter/flutter/issues/21474

user1978019
  • 3,008
  • 1
  • 29
  • 38