firebase / flutterfire

🔥 A collection of Firebase plugins for Flutter apps.
https://firebase.google.com/docs/flutter/setup
BSD 3-Clause "New" or "Revised" License
8.68k stars 3.97k forks source link

[firebase_admob] Banner ad not disposing on android sometimes? #3056

Closed Vijay053 closed 3 years ago

Vijay053 commented 4 years ago

Sometime ads on android doesn't dispose even after calling dispose. Users of my app are reporting that ads are covering their screens. 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 next screen.

I am not able to replicate the issue locally, but lots of my users has sent me screenshots where ad is covering next screen.

Flutter doctor Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel beta, 1.19.0-4.3.pre, on Mac OS X 10.15.5 19F101, locale en-US)

[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3) [✓] Xcode - develop for iOS and macOS (Xcode 11.6) [✓] Chrome - develop for the web [✓] Android Studio (version 4.0) [✓] VS Code (version 1.47.2) [✓] Connected device (3 available)

• No issues found!

russellwheatley commented 3 years ago

The firebase_admob plugin will be deprecated in April 2021 in favor of Google Mobile Ads SDK for Flutter. Google Mobile Ads SDK for Flutter is a new Flutter plugin that supports more Ads formats than firebase_admob does. Google Mobile Ads SDK for Flutter currently supports loading and displaying banner, interstitial (full-screen), native ads, and rewarded video ads across AdMob and AdManager. It also supports displaying banner and native ads as Widgets as opposed to being overlayed over all app content. We're now recommending projects currently using firebase_admob migrate to Google Mobile Ads SDK for Flutter following the instructions outlined here. Issues with migrating or with using the new package should now be raised over on the Google Mobile Ads SDK for Flutter repository.