googleads / googleads-mobile-flutter

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

Ad content is not adjusted #570

Closed Adriup closed 2 years ago

Adriup commented 2 years ago

Hello, I have a problem with the display of ads on some devices, in which the layout of the ad content is not adjusted correctly, this occurs for both banner and interstitial.

Has anyone had this problem and know how to solve it?

This issue is causing disruptive ad violation on google play.

The version I'm using is google_mobile_ads: ^1.2.0

Below are screenshot examples of the problem.

Thank you for your attention.

Image 1

Image 2

maheshj01 commented 2 years ago

Hi @Adriup, Thanks for filing the issue. Can you please share the minimal and complete code sample along with the output of flutter doctor -v and the device name on which this issue occurs?

Adriup commented 2 years ago

Hi @maheshmnj, the device I detected the problem on was a Samsung A52. I will add the required information below. Thank you for your attention. I was using Flutter version 2.8, but I updated to 3, and the same error kept happening.

C:\Users\Computador>flutter doctor -v
[√] Flutter (Channel stable, 3.0.1, on Microsoft Windows [versÆo 10.0.19044.1706], locale pt-BR)
    • Flutter version 3.0.1 at C:\src\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision fb57da5f94 (5 days ago), 2022-05-19 15:50:29 -0700
    • Engine revision caaafc5604
    • Dart version 2.17.1
    • DevTools version 2.12.2

[!] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
    • Android SDK at C:\Users\Computador\AppData\Local\Android\sdk
    X cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    X Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[√] Android Studio (version 2021.1)
    • 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.11+9-b60-7590822)

[√] VS Code (version 1.67.2)
    • VS Code at C:\Users\Computador\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.40.0

[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [versÆo 10.0.19044.1706]
    • Chrome (web)      • chrome  • web-javascript • Google Chrome 102.0.5005.62
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 101.0.1210.53

[√] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 2 categories.

Code:

code sample ```dart import 'package:flutter/material.dart'; import 'package:flutter/src/foundation/key.dart'; import 'package:flutter/src/widgets/framework.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; class TelaResultado extends StatefulWidget { final resultado; const TelaResultado({Key? key, required this.resultado}) : super(key: key); @override State createState() => _TelaResultadoState(); } class _TelaResultadoState extends State { // Anuncios BannerAd? _anchoredAdaptiveAd; bool _isLoaded = false; late Orientation _currentOrientation; InterstitialAd? _interstitialAd; int _numInterstitialLoadAttempts = 0; int maxFailedLoadAttempts = 3; static final AdRequest request = AdRequest( keywords: ['foo', 'bar'], contentUrl: 'http://foo.com/bar.html', nonPersonalizedAds: true, ); @override void didChangeDependencies() { super.didChangeDependencies(); _currentOrientation = MediaQuery.of(context).orientation; _loadAd(); } @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) async { carregarAnuncios(); setState(() {}); }); super.initState(); } @override void dispose() { super.dispose(); _anchoredAdaptiveAd?.dispose(); _interstitialAd?.dispose(); } carregarAnuncios() { _createInterstitialAd(); } Future _loadAd() async { await _anchoredAdaptiveAd?.dispose(); setState(() { _anchoredAdaptiveAd = null; _isLoaded = false; }); final AnchoredAdaptiveBannerAdSize? size = await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize( MediaQuery.of(context).size.width.truncate()); if (size == null) { print('Unable to get height of anchored banner.'); return; } _anchoredAdaptiveAd = BannerAd( adUnitId: 'adId', size: size, request: AdRequest(), listener: BannerAdListener( onAdLoaded: (Ad ad) { print('$ad loaded: ${ad.responseInfo}'); setState(() { // When the ad is loaded, get the ad size and use it to set // the height of the ad container. _anchoredAdaptiveAd = ad as BannerAd; _isLoaded = true; }); }, onAdFailedToLoad: (Ad ad, LoadAdError error) { print('Anchored adaptive banner failedToLoad: $error'); ad.dispose(); }, ), ); return _anchoredAdaptiveAd!.load(); } Widget _getAdWidget() { return OrientationBuilder( builder: (context, orientation) { if (_currentOrientation == orientation && _anchoredAdaptiveAd != null && _isLoaded) { return Container( color: Colors.green, width: _anchoredAdaptiveAd!.size.width.toDouble(), height: _anchoredAdaptiveAd!.size.height.toDouble(), child: AdWidget(ad: _anchoredAdaptiveAd!), ); } // Reload the ad if the orientation changes. if (_currentOrientation != orientation) { _currentOrientation = orientation; _loadAd(); } return Container(); }, ); } void _createInterstitialAd() { InterstitialAd.load( adUnitId: 'adID', request: request, adLoadCallback: InterstitialAdLoadCallback( onAdLoaded: (InterstitialAd ad) { print('$ad loaded'); _interstitialAd = ad; _numInterstitialLoadAttempts = 0; _interstitialAd!.setImmersiveMode(true); }, onAdFailedToLoad: (LoadAdError error) { print('InterstitialAd failed to load: $error.'); _numInterstitialLoadAttempts += 1; _interstitialAd = null; if (_numInterstitialLoadAttempts < maxFailedLoadAttempts) { _createInterstitialAd(); } }, )); } void _showInterstitialAd() { if (_interstitialAd == null) { Navigator.pop(context); } _interstitialAd!.fullScreenContentCallback = FullScreenContentCallback( onAdShowedFullScreenContent: (InterstitialAd ad) => print('ad onAdShowedFullScreenContent.'), onAdDismissedFullScreenContent: (InterstitialAd ad) async { print('$ad onAdDismissedFullScreenContent.'); ad.dispose(); Navigator.pop(context); }, onAdFailedToShowFullScreenContent: (InterstitialAd ad, AdError error) async { print('$ad onAdFailedToShowFullScreenContent: $error'); ad.dispose(); Navigator.pop(context); }); _interstitialAd!.show(); _interstitialAd = null; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Quiz Bíblico"), ), body: Container( child: Column( children: [ _getAdWidget(), Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( "assets/pontos.png", width: 200, height: 200, ), Padding( padding: const EdgeInsets.all(8.0), child: Text( "Resultado: ${widget.resultado}", style: const TextStyle(fontSize: 20, color: Colors.black), ), ), ], ), ), ), ], ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, floatingActionButton: FloatingActionButton.extended( onPressed: () { _showInterstitialAd(); }, tooltip: 'Voltar', label: Text( 'Voltar', style: TextStyle( color: Colors.white, ), ), icon: Icon( Icons.arrow_back_ios, color: Colors.white, ), ), ); } } ```
nickJLm commented 2 years ago

Our team is seeing this issue, and we saw that when the banner is changing after 30 seconds, the size of the banner that is coming back from getPlatformAdSize() is incorrect. This causes the layout of the banner not to be adjusted accordingly.

maheshj01 commented 2 years ago

Thanks for the code sample @Adriup, I tried to run your code sample But the ad fails to load with error

Anchored adaptive banner failedToLoad: LoadAdError(code: 3

Restarted application in 916ms.
D/DynamitePackage(23209): Instantiating com.google.android.gms.ads.ChimeraAdManagerCreatorImpl
I/Ads     (23209): Use RequestConfiguration.Builder().setTestDeviceIds(Arrays.asList("37B2E83F0935251E53408AEA377C62CD")) to get test ads on this device.
E/FrameEvents(23209): updateAcquireFence: Did not find frame.
E/FrameEvents(23209): updateAcquireFence: Did not find frame.
E/FrameEvents(23209): updateAcquireFence: Did not find frame.
I/Ads     (23209): Ad failed to load : 3
I/flutter (23209): Anchored adaptive banner failedToLoad: LoadAdError(code: 3, domain: com.google.android.gms.ads, message: Publisher data not found. <https://support.google.com/admob/answer/9905175#9>, responseInfo: ResponseInfo(responseId: null, mediationAdapterClassName: , adapterResponses: []))

Labeling this issue as a bug for further investigation

code sample ```dart // import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; class TelaResultado extends StatefulWidget { final resultado; const TelaResultado({Key? key, required this.resultado}) : super(key: key); @override State createState() => _TelaResultadoState(); } class _TelaResultadoState extends State { // Anuncios BannerAd? _anchoredAdaptiveAd; bool _isLoaded = false; late Orientation _currentOrientation; static const AdRequest request = AdRequest( keywords: ['foo', 'bar'], contentUrl: 'http://foo.com/bar.html', nonPersonalizedAds: true, ); @override void didChangeDependencies() { super.didChangeDependencies(); _currentOrientation = MediaQuery.of(context).orientation; _loadAd(); } @override void initState() { super.initState(); } @override void dispose() { super.dispose(); _anchoredAdaptiveAd?.dispose(); } Future _loadAd() async { setState(() { _anchoredAdaptiveAd = null; _isLoaded = false; }); final AnchoredAdaptiveBannerAdSize? size = await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize( MediaQuery.of(context).size.width.truncate()); if (size == null) { print('Unable to get height of anchored banner.'); return; } _anchoredAdaptiveAd = BannerAd( adUnitId: 'ca-app-pub-3940256099942544/630097811', size: size, request: request, // listener: const BannerAdListener(), listener: BannerAdListener( onAdLoaded: (Ad ad) { print('$ad loaded: ${ad.responseInfo}'); setState(() { // When the ad is loaded, get the ad size and use it to set // the height of the ad container. _anchoredAdaptiveAd = ad as BannerAd; _isLoaded = true; }); }, onAdFailedToLoad: (Ad ad, LoadAdError error) { print('Anchored adaptive banner failedToLoad: $error'); ad.dispose(); }, ), ); await _anchoredAdaptiveAd!.load(); setState(() { _isLoaded = true; }); } Widget _getAdWidget() { return OrientationBuilder( builder: (context, orientation) { if (_currentOrientation == orientation && _anchoredAdaptiveAd != null && _isLoaded) { return Container( // color: Colors.green, width: _anchoredAdaptiveAd!.size.width.toDouble(), height: _anchoredAdaptiveAd!.size.height.toDouble(), child: AdWidget(ad: _anchoredAdaptiveAd!), ); } // Reload the ad if the orientation changes. if (_currentOrientation != orientation) { _currentOrientation = orientation; _loadAd(); } return Container( height: 100, color: Colors.red, ); }, ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Quiz Bíblico"), ), body: Container( child: Column( children: [ _getAdWidget(), Expanded( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( "assets/flutter_engage.jpeg", width: 200, height: 200, ), Padding( padding: const EdgeInsets.all(8.0), child: Text( "Resultado: ${widget.resultado}", style: const TextStyle(fontSize: 20, color: Colors.black), ), ), ], ), ), ), ], ), ), ); } } void main() { WidgetsFlutterBinding.ensureInitialized(); //Running the app without the below code will print the device id in log cat MobileAds.instance.updateRequestConfiguration( RequestConfiguration(testDeviceIds: ['INSERT TEST DEVICE ID HERE'])); MobileAds.instance.initialize(); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: const TelaResultado( resultado: null, ), ); } } ```
Johnblundon commented 2 years ago

This is still a major issue as we only get the correct height from _adSize.height.toDouble() for the very first banner. It passes the exact same size every-time even when the banners are smaller or larger. Is there any progress or fix for this? It's incredibly annoying and look really bad.

timothyhoang-google commented 2 years ago

We can't prioritize investigating this issue unless there is a reproducible sample.

github-actions[bot] commented 2 years ago

Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now. If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones. Thanks for your contribution.