1

Sometimes ads on android don't dispose of even after calling dispose. Since the banner is an overlay, it covers the next screen. Users of my app are reporting that ads are covering their screens because the ad from the previous screen was not disposed. I have seen this issue (https://github.com/FirebaseExtended/flutterfire/issues/96) and I have tried to handle it. Following is my code to handle one ad unit.

import 'package:firebase_admob/firebase_admob.dart';
import 'package:sampleapp/utilities/logger.dart';

enum AdUnitType { banner, interstitialAd }
enum AdUnitState { loading, loaded, showing, shown, disposing, dispose }

class AdUnitHandler {
  final String _adUnitId;
  final AdUnitType _adUnitType;
  final AdSize adSize;
  String adSizeString;
  MobileAd adUnit;
  bool _isLoaded;

  AdUnitHandler(
    this._adUnitId,
    this._adUnitType, {
    this.adSize = AdSize.banner,
  });

  Future<bool> load() async {
    await dispose();
    _isLoaded = false;
    switch (_adUnitType) {
      case AdUnitType.banner:
        adUnit = BannerAd(adUnitId: _adUnitId, size: adSize);
        adSizeString = adSize == AdSize.banner ? 'banner' : 'mediumRect';
        break;
      case AdUnitType.interstitialAd:
        adUnit = InterstitialAd(adUnitId: _adUnitId);
        adSizeString = 'interstitial';
        break;
    }
    adUnit.listener = (MobileAdEvent event) {
      Log.d('ad event $event');
      switch (event) {
        case MobileAdEvent.loaded:
          _isLoaded = true;
          break;
        case MobileAdEvent.failedToLoad:
        case MobileAdEvent.clicked:
        case MobileAdEvent.impression:
        case MobileAdEvent.opened:
        case MobileAdEvent.leftApplication:
          //do nothing
          break;
        case MobileAdEvent.closed:
          dispose();
          break;
      }
    };
    Log.d('Loading ad');
    return adUnit.load();
  }

  Future<bool> show() async {
    return adUnit?.show();
  }

  Future<void> dispose() async {
    if (adUnit == null) return;
    try {
      if (!_isLoaded) {
        int count = 0;
        await Future.doWhile(() async {
          if (await adUnit?.isLoaded()) {
            return false;
          }
          Log.d('ad is loading before dispose');
          await Future.delayed(Duration(seconds: 1));
          count++;
          if (count == 30) return false;
          return true;
        });
      }
      Log.d('Disposing ad');
      adUnit?.dispose();
      adUnit = null;
      _isLoaded = false;
    } catch (e) {
      Log.d('ad failed to dispose - $e');
    }
  }
}

I am calling dispose method at two places:

  1. dispose method of Stateful widget.
  2. Before navigating to the next screen. I am not able to replicate the issue locally, but lots of my users have sent me screenshots where the ad is covering the next screen.

Thanks

Swaroop Humane
  • 1,770
  • 1
  • 7
  • 17
vijay053
  • 822
  • 3
  • 18
  • 36

0 Answers0