googleads / googleads-mobile-flutter

A Flutter plugin for the Google Mobile Ads SDK
Apache License 2.0
344 stars 285 forks source link

google_mobile_ads SafeArea override #635

Closed under3415 closed 1 year ago

under3415 commented 2 years ago

Steps to Reproduce

This one is a bit complicated, not sure if I am doing something wrong or if it is a bug or just how things are supposed to work. I need some help here please!

I have a rewarded ad displayed in my app. This is implemented pretty vanilla way and it does work, the video ad plays across the entire screen. But there are some weird things happening to the application behind the ad which you cannot really see unless you have a phone with a notch (Samsung A20 in my case).

When the ad runs on a phone with a notch, the ad respects the SafeArea and does not cover the top part of the screen which is normally taken by Android status bar. But it seems that the ad affects the application, so application no longer respects SafeArea and it stretches over all the way to the top of the screen. So you can see the sliver of the app behind the ad, in the area where status bar normally is. I mean it is not the end of the world, but it looks ugly.

So in a nutshell, when the ad starts, it changes the way application behind is displayed which you mostly would not notice except if there is a notch (or you use media query to resize things).

Is this normal? Am I doing something wrong? How to avoid this ugly glitch?

Expected results: App is not visible behind the ad

Actual results: Sliver of the app visible around the notch in "unsafe area"

Code sample ```use google_mobile_ad rewarded ad sample with a phone with a notch ```
Logs ``` ``` ``` ``` ``` [√] Flutter (Channel beta, 3.3.0-0.5.pre, on Microsoft Windows [Version 10.0.19044.1949], locale en-US) • Flutter version 3.3.0-0.5.pre on channel beta at C:\src\flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 096162697a (9 days ago), 2022-08-22 15:34:14 -0700 • Engine revision ad3d868e0d • Dart version 2.18.0 (build 2.18.0-271.7.beta) • DevTools version 2.15.0 [√] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) • Android SDK at C:\Users\dejan\AppData\Local\Android\sdk • Platform android-32, build-tools 32.1.0-rc1 • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [!] Visual Studio - develop for Windows (Visual Studio Community 2022 17.3.2) • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community • Visual Studio Community 2022 version 17.3.32819.101 • Windows 10 SDK version 10.0.22000.0 X Visual Studio is missing necessary components. Please re-run the Visual Studio installer for the "Desktop development with C++" workload, and include these components: MSVC v142 - VS 2019 C++ x64/x86 build tools - If there are multiple build tool versions available, install the latest C++ CMake tools for Windows Windows 10 SDK [√] Android Studio (version 2021.2) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840) [√] VS Code (version 1.70.2) • VS Code at C:\Users\dejan\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.46.0 [√] Connected device (3 available) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19044.1949] • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 • Edge (web) • edge • web-javascript • Microsoft Edge 104.0.1293.70 [√] HTTP Host Availability • All required HTTP hosts are available ```

image

darshankawar commented 2 years ago

@under3415 Can you provide a minimal reproducible code sample without any third party plugins that shows this behavior ? What type of ad are you showing or it happens with all ads ?

Also, can you try below and see if it works ?

Add SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); before showing the ad, then on dismiss call SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);

under3415 commented 2 years ago

@under3415 Can you provide a minimal reproducible code sample without any third party plugins that shows this behavior ? What type of ad are you showing or it happens with all ads ?

Also, can you try below and see if it works ?

Add SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive); before showing the ad, then on dismiss call SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);

  1. I can try a reproducible code sample. What would help is having an emulator with a notch. Do you know how can I get that?
  2. This happens with all rewarded ads. Are you saying that you are not seeing this or have you not tested with notched phones? What happens when you play an ad on a phone with a notch? Does the ad ignore SafeArea and cover the entire screen, or does it leave status bar in the "unsafe area" and only covers part of the screen? Which one do you get?
  3. In my code I had await _rewardedAd!.setImmersiveMode(true); before showing the ad. I have tried to set this to "false", but no difference. Is this different from what you are suggesting with SystemChrome.setEnabledSystemUIMode?
under3415 commented 2 years ago

OK, here is the reproducible code. Tested on an emulator and a physical device with a notch.

Below is a screenshot from my physical device. You can see the app bar behind the ad. Normally this is where the status bar is. So the ad somehow stretches the app out of the SafeArea.

image

  1. Run `flutter create test'
  2. Add google_mobile_ads: ^2.0.1 to pubspec.yaml
  3. Modify /android/app/build.gradle as follows:
    minSdkVersion 26
    targetSdkVersion 32
  4. Use the latest stable flutter SDK (3.3.0, as of September 2nd, 2022)
  5. Edit android manifest to add sample Google ads application id:
    <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-3940256099942544~3347511713"/>
  6. Paste this code in main.dart:
    
    import 'package:flutter/material.dart';
    import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() { runApp(const MyApp()); }

class MyApp extends StatelessWidget { const MyApp({super.key});

// This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'Google Ads Demo'), ); } }

class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title});

final String title;

@override State createState() => _MyHomePageState(); }

class _MyHomePageState extends State { RewardedAd? _rewardedAd; bool _loadingAd = false;

Future _adBuyDialog() { return showGeneralDialog( context: context, barrierDismissible: false, transitionBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition( opacity: animation, child: ScaleTransition( scale: animation, child: child, ), ); }, pageBuilder: (context, animation, secondaryAnimation) { return SafeArea( child: Scaffold( backgroundColor: Colors.amber, body: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.green, elevation: 0, minimumSize: const Size( 150, 50, )), onPressed: () async { await showRewardedAd(); if (!mounted) { return; } Navigator.pop(context); }, child: const Padding( padding: EdgeInsets.all(8.0), child: Text( "Watch Ad", style: TextStyle(color: Colors.black, fontSize: 12), ), ), ), ), ); }, ); }

Future get _createRewardedAd async { _loadingAd = true; await RewardedAd.load( adUnitId: 'ca-app-pub-3940256099942544/5224354917', //sample ads request: const AdRequest(), rewardedAdLoadCallback: RewardedAdLoadCallback( onAdLoaded: (RewardedAd ad) { _rewardedAd = ad; _loadingAd = false; }, onAdFailedToLoad: (LoadAdError error) { _rewardedAd = null; _loadingAd = false; }, )); }

Future showRewardedAd() async { int tries = 0; int maxTries = 5;

if (_rewardedAd == null) {
  while (tries < maxTries) {
    if (!_loadingAd) {
      _createRewardedAd;
    }
    await Future.delayed(const Duration(seconds: 1));

    tries++;

    if (_rewardedAd != null) {
      break;
    } else if (tries >= maxTries) {
      await showDialog(
          context: context,
          builder: (BuildContext context) {
            return AlertDialog(
              title: const Text("Ad Error"),
              content: const Text(
                  "Ad taking longer to load. Check the Internet. Continue waiting?"),
              actions: <Widget>[
                Semantics(
                  button: true,
                  label: "OK",
                  child: TextButton(
                    child: const Text("OK"),
                    onPressed: () {
                      tries = -2;
                      Navigator.of(context).pop();
                    },
                  ),
                ),
                Semantics(
                  button: true,
                  label: "Cancel",
                  child: TextButton(
                    child: const Text("Cancel"),
                    onPressed: () {
                      //remove screen scaling ban
                      Navigator.of(context).pop();
                    },
                  ),
                ),
              ],
            );
          });
    }
  }
}

if (_rewardedAd == null) {
  if (!_loadingAd) {
    _createRewardedAd;
  }

  return;
}

_rewardedAd!.fullScreenContentCallback = FullScreenContentCallback(
  onAdDismissedFullScreenContent: (RewardedAd ad) {
    ad.dispose();
    _rewardedAd = null;
  },
  onAdFailedToShowFullScreenContent: (RewardedAd ad, AdError error) async {
    ad.dispose();
    _rewardedAd = null;
    //_createRewardedAd;
  },
);
await _rewardedAd!.show(
    onUserEarnedReward: (AdWithoutView ad, RewardItem reward) {
  print("rewarded");
});

}

Future _initAds() async { await MobileAds.instance.initialize(); await _createRewardedAd; return true; }

@override Widget build(BuildContext context) { return SafeArea( child: Scaffold( appBar: AppBar( title: Text(widget.title), ), body: FutureBuilder( future: _initAds(), builder: (context, snapshot) { if (snapshot.hasData) { return const Center( child: Text( 'Click to show test ad', ), ); } else { return const Center( child: SizedBox( width: 60, height: 60, child: CircularProgressIndicator( strokeWidth: 8.0, color: Color.fromRGBO(69, 162, 158, 1.0), ), ), ); } }), floatingActionButton: FloatingActionButton( onPressed: _adBuyDialog, tooltip: 'Show Ad', child: const Icon(Icons.add), ), ), ); } }

darshankawar commented 2 years ago

Thanks for the code sample. Using it, I was able to replicate the behavior using Pixel emulator that has a notch.

Maybe similar / related: https://github.com/googleads/googleads-mobile-flutter/issues/191

under3415 commented 2 years ago

Thanks for the code sample. Using it, I was able to replicate the behavior using Pixel emulator that has a notch.

Maybe similar / related: #191

I actually cannot replicate this on Pixel 5 which has a camera in top left corner. Which emulator are you using?

under3415 commented 2 years ago

The issue has miraculously disappeared without a package update! Perhaps it was fixed on Google ad servers?

sharyer-Ilyas-Khan commented 2 years ago

issue can be resolved by adding below line `shortEdges

?android:colorBackground` in android/app/src/main/res/values/style.xml.
under3415 commented 1 year ago

Hi, this issue is back! I can reproduce both on my physical phone and Pixel 6 Pro emulator that comes with Android Studio. What's worse the back button does not work and the user has no way to stop the ad from playing!

Use above reproducible example, just update everything to the latest version.

google_mobile_ads: ^3.0.0

[√] Flutter (Channel stable, 3.10.0, on Microsoft Windows [Version 10.0.19045.2965], locale en-US)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
[√] Android Studio (version 2022.2)
[√] VS Code (version 1.78.1)
huycozy commented 1 year ago

We’re closing this issue due to inactivity. If you’re still impacted, please create a new issue via the Developer Forum.

AMER88795 commented 10 months ago

Steps to Reproduce

This one is a bit complicated, not sure if I am doing something wrong or if it is a bug or just how things are supposed to work. I need some help here please!

I have a rewarded ad displayed in my app. This is implemented pretty vanilla way and it does work, the video ad plays across the entire screen. But there are some weird things happening to the application behind the ad which you cannot really see unless you have a phone with a notch (Samsung A20 in my case).

When the ad runs on a phone with a notch, the ad respects the SafeArea and does not cover the top part of the screen which is normally taken by Android status bar. But it seems that the ad affects the application, so application no longer respects SafeArea and it stretches over all the way to the top of the screen. So you can see the sliver of the app behind the ad, in the area where status bar normally is. I mean it is not the end of the world, but it looks ugly.

So in a nutshell, when the ad starts, it changes the way application behind is displayed which you mostly would not notice except if there is a notch (or you use media query to resize things).

Is this normal? Am I doing something wrong? How to avoid this ugly glitch?

Expected results: App is not visible behind the ad

Actual results: Sliver of the app visible around the notch in "unsafe area"

Code sample ```use google_mobile_ad rewarded ad sample with a phone with a notch ```
Logs ``` ``` ``` ``` ``` [√] Flutter (Channel beta, 3.3.0-0.5.pre, on Microsoft Windows [Version 10.0.19044.1949], locale en-US) • Flutter version 3.3.0-0.5.pre on channel beta at C:\src\flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 096162697a (9 days ago), 2022-08-22 15:34:14 -0700 • Engine revision ad3d868e0d • Dart version 2.18.0 (build 2.18.0-271.7.beta) • DevTools version 2.15.0 [√] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1) • Android SDK at C:\Users\dejan\AppData\Local\Android\sdk • Platform android-32, build-tools 32.1.0-rc1 • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840) • All Android licenses accepted. [√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe [!] Visual Studio - develop for Windows (Visual Studio Community 2022 17.3.2) • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community • Visual Studio Community 2022 version 17.3.32819.101 • Windows 10 SDK version 10.0.22000.0 X Visual Studio is missing necessary components. Please re-run the Visual Studio installer for the "Desktop development with C++" workload, and include these components: MSVC v142 - VS 2019 C++ x64/x86 build tools - If there are multiple build tool versions available, install the latest C++ CMake tools for Windows Windows 10 SDK [√] Android Studio (version 2021.2) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840) [√] VS Code (version 1.70.2) • VS Code at C:\Users\dejan\AppData\Local\Programs\Microsoft VS Code • Flutter extension version 3.46.0 [√] Connected device (3 available) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19044.1949] • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80 • Edge (web) • edge • web-javascript • Microsoft Edge 104.0.1293.70 [√] HTTP Host Availability • All required HTTP hosts are available ```

image

https://user-images.githubusercontent.com/3857822/188045708-4082bb0b-42c5-4b5f-9163-f57242bd689c.png