Flutterfire: [firebase_admob] ads invades safe area and close button is blocked on iPhone X

Created on 4 Aug 2020  ·  18Comments  ·  Source: FirebaseExtended/flutterfire

Describe the bug
Some of the interstitial ads are not rendered right on iPhone X, the close button is blocked.

To Reproduce

  1. Create project with firebase_admob 0.9.3+4 and pod 'Google-Mobile-Ads-SDK' ~> '7.63.0'
  2. Build and install release app on iPhone X 13.6
  3. Some of the interstitial ads are not rendered right on iPhone X, the close button is blocked. Mostly games.

Expected behavior
Ad displayed within safe area

Additional context
Screenshots:

ảnh
ảnh-2
ảnh-3

bitcoin ios admob bug

Most helpful comment

Having the same problem
Temporary solution:
Hide status bar when ads are shown

listener: (MobileAdEvent event) {
      if (event == MobileAdEvent.closed) {
        SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
      }
      if (event == MobileAdEvent.clicked) {
        SystemChrome.setEnabledSystemUIOverlays([]);
      }
},

Hope this issue will be fixed asap

All 18 comments

I’m having the exact same problem. They closed my ticked as you had already reported it.

This doesn't seem right. This is a duplicate of https://github.com/FirebaseExtended/flutterfire/issues/2531.

@jjliu15 how is this handled in the AdMob SDK?

This doesn't seem right. This is a duplicate of #2531.

@jjliu15 how is this handled in the AdMob SDK?

I've never had this issue on rewarded ads. Only in interstitial.

2531 is only rewarded ads, look like many fullscreen ads has this issue.

I have same issue in interstitial ad.

My app users complain to me about this.
This is severe because user should close app completely and start app again. (swipe back is also not working)
This is terrible User Experience

It can be reproduced simply on test ads and simulator (iPhone SE, non-notch)

스크린샷 2020-10-04 오전 3 26 45

Upper half of close button is overlapped with status bar,
Lower half is not overlapped with status bar.

Upper half cannot be touched.
Close button should not be overlapped with status bar (in notch style, it seems not overlap)

Same here :(

Many 1 star due to this lroblem, we need a fix

Is there any update on this? I had to disable the interstitial ads on most of my apps? I can't believe it is not a high priority issue.

I think this problem ist not only relevant on iOS, but on android devices with rounded corners as well. For example I can reproduce this behaviour on a Google Pixel 4.

Looking into the code the native part only invokes the show method of the InterstialAd class. I guess one cannot do much here, since the layout happens inside of the AdMob Library?

Same problem here. We need a solution

I found a workaround. If you hide the status bar in the presenting viewcontroller before the interstitial is presented, it obviously won't cover the close button.
You can hide the status bar by overwriting preferStatusbarHidden method

- (BOOL) prefersStatusBarHidden {
    return  hideStatusbar;
}

hideStatusbar = true;
[self prefersStatusBarHidden];
[self.admMobInterstitial presentFromRootViewController:self];

- (void) interstitialDidDismissScreen:(GADInterstitial *)interstitial {
    hideStatusbar = false;
    [self setNeedsStatusBarAppearanceUpdate];
}

- (void) interstitialWillLeaveApplication:(GADInterstitial *)ad {
    hideStatusbar = false;
    [self setNeedsStatusBarAppearanceUpdate];
}

If you don't have full control from which viewcontroller it's presented from
It is a bit of a hack using the setStatusBarHidden deprecated API:

Before you present the interstitial, save the prefersStatusBarHidden value for the viewcontroller

statusBarHiddenForPresentingRootVC = rootVC.prefersStatusBarHidden;
[self.admMobInterstitial presentFromRootViewController:rootVC];

- (void) interstitialWillPresentScreen:(GADInterstitial *)ad {
    if (statusBarHiddenForPresentingRootVC == false) {
        [[UIApplication sharedApplication] setStatusBarHidden:YES];
    }
}

When the interstitial is dismissed or tapped, restore the statusbarHidden value

- (void) interstitialDidDismissScreen:(GADInterstitial *)interstitial {
    if (statusBarHiddenForPresentingRootVC == false) {
        [[UIApplication sharedApplication] setStatusBarHidden:false];
    }
}

- (void) interstitialWillLeaveApplication:(GADInterstitial *)ad {
    if (statusBarHiddenForPresentingRootVC == false) {
        [[UIApplication sharedApplication] setStatusBarHidden:false];
    }
}

Same problem here. I'm using firebase_admob: ^0.10.2. Close Button do not work.

Simulator Screen Shot - iPhone 12 Pro Max - 2020-11-07 at 22 44 25

hiding the statusbar fixes for me, however it's not the best way, but works:
SystemChrome.setEnabledSystemUIOverlays([]);

Having the same problem
Temporary solution:
Hide status bar when ads are shown

listener: (MobileAdEvent event) {
      if (event == MobileAdEvent.closed) {
        SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
      }
      if (event == MobileAdEvent.clicked) {
        SystemChrome.setEnabledSystemUIOverlays([]);
      }
},

Hope this issue will be fixed asap

"Hide status bar" works.
Thanks @Tibbs and @shunnokw

Testing (iOS 14.1):
iPhone 12/ iPhone 12 Pro / iPhone 12 Pro Max (Simulator*): NOT WORK
iPhone 12/ iPhone 12 Pro / iPhone 12 Pro Max (Real device): WORK (Reported by users)
iPhone 11 Pro Max (Device/Simulator): Work
iPhone 11 / iPhone 11 Pro (Simulator): Work

Thank you for the solution, Tested with real device iPhone 12 Pro Max : WORK

One issue is I added this ads on an Exit button where I pop the page. So in this case since I pop then the if (event == MobileAdEvent.closed) condition will never trigger. So the status bar will be hidden and not be displayed again after ads is closed. Any solution?

This is my code:

RaisedButton(
                color: Colors.blueAccent,
                padding: EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 6.0),
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(Radius.circular(22.0))),
                onPressed: ()
                {
                  AdsProvider.showInterstitialAd();
                   Navigator.of(context).pop();
                },
                child: Text(
                  '    Quit    ',
                  style: TextStyle(color: AppColors.withe),
                ),
              ),


**AdsProvider Class:**

static void _onInterstitialAdEvent(MobileAdEvent event) {
    switch (event) {
      case MobileAdEvent.loaded:
        _isInterstitialAdReady = true;
        print('Interstitial ad loaded');
        break;
      case MobileAdEvent.failedToLoad:
        _isInterstitialAdReady = false;
        print('Failed to load an interstitial ad');
        break;
      case MobileAdEvent.closed:
        SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
        print('closed to load an interstitial ad');
        //context.bloc<ProgramCubit>().startProgram( context,_program);
        break;
      case MobileAdEvent.clicked:
        print('clicked to hide top bar');
        SystemChrome.setEnabledSystemUIOverlays([]);
        break;
      default:
      // do nothing
    }
  }

  static void readyInterstitialAd() {
    _isInterstitialAdReady = false;

    _interstitialAd = InterstitialAd(
      adUnitId: AdManager.interstitialAdUnitId,
      listener: _onInterstitialAdEvent,
    );
    _interstitialAd.load();
  }

  static void showInterstitialAd(bool isTime) {
    if (_isInterstitialAdReady) {
      _interstitialAd.show();
    }
  }
Was this page helpful?
0 / 5 - 0 ratings