Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AdManagerBannerAd flickering and fails to display in Android Samsung #1229

Closed
memoriasIT opened this issue Jan 15, 2025 · 15 comments
Closed

Comments

@memoriasIT
Copy link

memoriasIT commented Jan 15, 2025

Environment

Flutter 3.27.2 on macOS, compiling to android as APK.
See Flutter doctor at the end for more info.

Plugin Version

5.2.0

Describe the problem

Using a minimal implementation of an AdManagerBannerAd in a ListView the ads flicker and don't show in the phone "Samsung Galaxy A51, with Android 13". The issue doesn't seem to appear in iOS (or at least not in the iPhones I tried with).

Other phones that I tested it with:

  • Xiaomi POCO X3 Pro, with Android 11: works fine
  • Pixel 6 (Android 15): works fine
  • Samsung S21 (Android 14): does briefly flicker
  • Samsung S20 (Android 12, One UI 4.1): Does show some artifacts

It will also behave fine in emulators. Here I provide two videos:

Emulator (works fine)
https://github.com/user-attachments/assets/6d4dd790-ddaf-43e1-bdd8-a64a20ade839

Failing to work (Samsung Galaxy A51) |

Screen_recording_20250115_133226.mp4

Steps to Reproduce

  1. Use the provided example code.
  2. Run with flutter run
  3. When scrolling artifacts will appear and the ads won't show.

Expected results:

The ads load without any issues.

Actual results:

The ads don't show and there are artifacts in Samsung Galaxy A51.

Other relevant information

I tried with Flutter 3.27.1 and 3.27.2
I also tried with a fork of the package and updating the webview related dependencies. But it also did not work:
https://github.com/memoriasIT/googleads-mobile-flutter/blob/patch-1/packages/google_mobile_ads/pubspec.yaml

Code

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    const MaterialApp(
      home: GoogleAdsTest(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 50,
        itemBuilder: (context, index) {
          final isAd = (index + 1) % 10 == 0;

          if (isAd) return const TestAd();

          return Container(
            height: 50,
            color: index.isOdd ? Colors.red : Colors.blue,
            alignment: Alignment.center,
            margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
            child: Text(
              'Item ${index + 1}',
              style: const TextStyle(color: Colors.white, fontSize: 18),
            ),
          );
        },
      ),
    );
  }
}

class TestAd extends StatefulWidget {
  const TestAd({super.key});

  @override
  State<TestAd> createState() => _TestAdState();
}

class _TestAdState extends State<TestAd> {
  AdManagerBannerAd? _bannerAd;
  bool _isLoaded = false;

  @override
  void initState() {
    super.initState();
    unawaited(_loadAd());
  }

  @override
  Widget build(BuildContext context) {
    if (_bannerAd != null && _isLoaded) {
      return SizedBox(
        width: 320,
        height: 250,
        child: Align(alignment: Alignment.bottomCenter, child: AdWidget(ad: _bannerAd!)),
      );
    }

    return const SizedBox.shrink();
  }

  Future<void> _loadAd() async {
    if (!mounted) {
      return;
    }

    // Only recreate the ad once
    if (_bannerAd == null) {
      _bannerAd = AdManagerBannerAd(
        adUnitId: 'ca-app-pub-3940256099942544/9214589741',
        request: const AdManagerAdRequest(),
        sizes: [const AdSize(width: 320, height: 250)],
        listener: AdManagerBannerAdListener(
          onAdLoaded: (ad) {
            setState(() {
              _bannerAd = ad as AdManagerBannerAd;
              _isLoaded = true;
            });
          },
          onAdFailedToLoad: (ad, err) {
            debugPrint(err.toString());
            ad.dispose();
          },
        ),
      );
      await _bannerAd!.load();
    }
  }

  @override
  Future<void> dispose() async {
    unawaited(_bannerAd?.dispose());
    super.dispose();
  }
}

Logs

Unfortunately I am not able to provide logs from the Samsung Galaxy A51 as it's the client's phone.
But here I provide the logs for the android emulator.

Logs
[  +40 ms] The Flutter DevTools debugger and profiler on sdk gphone64 arm64 is available at:
           http://127.0.0.1:9100?uri=http://127.0.0.1:57375/3rxfcE_RqQs=/
[ +166 ms] D/CompatibilityChangeReporter(16222): Compat change id reported: 214741472; UID 10179; state: ENABLED
[   +2 ms] D/CompatibilityChangeReporter(16222): Compat change id reported: 171228096; UID 10179; state: ENABLED
[  +22 ms] D/AutofillManager(16222): Fill dialog is enabled:false, hints=[password, passwordAuto, creditCardNumber,
creditCardSecurityCode, creditCardExpirationDate]
[  +15 ms] W/test.development(16222): Accessing hidden method Landroid/media/AudioManager;->getOutputLatency(I)I (unsupported,
reflection, allowed)
[   +1 ms] W/cr_media(16222): BLUETOOTH_CONNECT permission is missing.
[        ] W/cr_media(16222): registerBluetoothIntentsIfNeeded: Requires BLUETOOTH permission
[  +14 ms] D/HostConnection(16222): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2
ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1
ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings
ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_vulkan_ignored_handles
ANDROID_EMU_has_shared_slots_host_memory_allocator ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8
ANDROID_EMU_vulkan_async_queue_submit ANDROID_EMU_vulkan_queue_submit_with_commands ANDROID_EMU_vulkan_batched_descriptor_set_update
ANDROID_EMU_sync_buffer_data ANDROID_EMU_vulkan_async_qsri ANDROID_EMU_read_color_buffer_dma ANDROID_EMU_hwc_multi_configs
GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object ANDROID_EMU_host_side_tracing ANDROID_EMU_gles_max_version_3_0 
[        ] D/EGL_emulation(16222): eglCreateContext: 0xb40000761bea08d0: maj 3 min 0 rcv 3
[        ] D/EGL_emulation(16222): eglMakeCurrent: 0xb40000761bea08d0: ver 3 0 (tinfo 0x7844605280) (first time)
[  +19 ms] D/EGL_emulation(16222): eglCreateContext: 0xb40000761bea08d0: maj 3 min 0 rcv 3
[  +59 ms] D/EGL_emulation(16222): eglCreateContext: 0xb40000761be9f550: maj 3 min 0 rcv 3
[ +135 ms] I/Ads     (16222): JS: The jsLoaded GMSG has been sent
(https://googleads.g.doubleclick.net/mads/static/mad/sdk/native/production/sdk-core-v40-impl.html:823)
[        ] I/chromium(16222): [INFO:CONSOLE(823)] "The jsLoaded GMSG has been sent", source:
https://googleads.g.doubleclick.net/mads/static/mad/sdk/native/production/sdk-core-v40-impl.html (823)
[  +73 ms] D/EGL_emulation(16222): eglCreateContext: 0xb40000761bea3990: maj 3 min 0 rcv 3
[  +10 ms] D/EGL_emulation(16222): eglCreateContext: 0xb40000761bea1c50: maj 3 min 0 rcv 3
[  +95 ms] D/CompatibilityChangeReporter(16222): Compat change id reported: 210923482; UID 10179; state: ENABLED
[   +8 ms] D/TrafficStats(16222): tagSocket(274) with statsTag=0xffffffff, statsUid=-1
[  +16 ms] I/PlatformViewsController(16222): Hosting view in view hierarchy for platform view: 0
[   +1 ms] I/PlatformViewsController(16222): PlatformView is using SurfaceProducer backend
[   +2 ms] W/Parcel  (16222): Expecting binder but got null!
[   +4 ms] E/FrameEvents(16222): updateAcquireFence: Did not find frame.
[   +5 ms] I/Ads     (16222): JS: The jsLoaded GMSG has been sent
(https://googleads.g.doubleclick.net/mads/static/mad/sdk/native/production/sdk-core-v40-impl.html:823)
[        ] I/chromium(16222): [INFO:CONSOLE(823)] "The jsLoaded GMSG has been sent", source:
https://googleads.g.doubleclick.net/mads/static/mad/sdk/native/production/sdk-core-v40-impl.html (823)
[   +5 ms] W/Parcel  (16222): Expecting binder but got null!
[  +16 ms] E/FrameEvents(16222): updateAcquireFence: Did not find frame.
[   +7 ms] E/FrameEvents(16222): updateAcquireFence: Did not find frame.
[  +32 ms] D/TrafficStats(16222): tagSocket(301) with statsTag=0xffffffff, statsUid=-1
[  +38 ms] E/FrameEvents(16222): updateAcquireFence: Did not find frame.
No issues found! (ran in 3.1s)
[✓] Flutter (Channel stable, 3.27.2, on macOS 15.0.1 24A348 darwin-arm64, locale en-US)
    • Flutter version 3.27.2 on channel stable at /Users/me/fvm/versions/3.27.2
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 68415ad1d9 (2 days ago), 2025-01-13 10:22:03 -0800
    • Engine revision e672b006cb
    • Dart version 3.6.1
    • DevTools version 2.40.2

[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /Users/me/android-sdk
    • Platform android-35, build-tools 34.0.0
    • ANDROID_SDK_ROOT = /Users/me/android-sdk
    • Java binary at: /usr/bin/java
    • Java version Java(TM) SE Runtime Environment (build 21.0.5+9-LTS-239)
    ! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses

[✓] Xcode - develop for iOS and macOS (Xcode 16.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16B40
    • CocoaPods version 1.16.2
@memoriasIT
Copy link
Author

memoriasIT commented Jan 15, 2025

Adding one more video on other device.
Samsung Galaxy S20, very small flickering is also present but not as bad as with A51

Screen_Recording_20250115_140426_BNR.dev.mp4

@memoriasIT
Copy link
Author

memoriasIT commented Jan 15, 2025

Recording it in the camera rather than in the phone shows more problems, specially when going bottom to top. However, my main concern is with the Samsung A51 where they do not show at all.

VID-20250115-WA0005.mp4

@memoriasIT
Copy link
Author

A different Samsung Galaxy A51 with Android 13 was tested, so it's reproducible on multiple phones.

Image

@malandr2
Copy link
Collaborator

Hi @memoriasIT, it appears your calling loadAd() every time the the banner widget comes onto the screen. Even after a banner is loaded, it looks like you're still calling loadAd(), such as when scrolling back up.

What if you loaded those ads only once and passed in the loaded ad to the appropriate ad index ? That may help with your performance issues

@malandr2 malandr2 added the feedback required Further information is requested label Jan 15, 2025
@memoriasIT
Copy link
Author

memoriasIT commented Jan 15, 2025

I did modify the code so the elements are preloaded.
I think this indeed help with the elements "jumping" but not with the artifacts that appear which I think are due to some other problem.

I also tried wrapping the ad with RepaintBoundary just in case, but it did nothing.

I don't have access to the Samsung A51 at the moment, but this is a video of a Samsung S20. The "artifacts" are more clear at the end of the video:

WhatsApp.Video.2025-01-15.at.18.25.49.mp4

I will try to get a video of the A51 running this tomorrow morning (GMT timezone), but I don't think this will fix it.

Code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    const MaterialApp(
      home: GoogleAdsTest(),
    ),
  );
}

class GoogleAdsTest extends StatefulWidget {
  const GoogleAdsTest({super.key});

  @override
  State<GoogleAdsTest> createState() => _GoogleAdsTestState();
}

class _GoogleAdsTestState extends State<GoogleAdsTest> {
  final Map<int, AdManagerBannerAd> _loadedAds = {};
  final Map<int, bool> _adLoadStatus = {};
  final int _adFrequency = 10;

  @override
  void initState() {
    super.initState();
    unawaited(_preloadAds());
  }

  @override
  void dispose() {
    // Dispose of all loaded ads to release resources
    for (final ad in _loadedAds.values) {
      unawaited(ad.dispose());
    }
    super.dispose();
  }

  Future<void> _preloadAds() async {
    for (var i = _adFrequency - 1; i < 50; i += _adFrequency) {
      await _loadAd(i);
    }
  }

  Future<void> _loadAd(int index) async {
    if (_loadedAds.containsKey(index)) return;

    final ad = AdManagerBannerAd(
      adUnitId: 'ca-app-pub-3940256099942544/9214589741',
      request: const AdManagerAdRequest(),
      sizes: [const AdSize(width: 320, height: 250)],
      listener: AdManagerBannerAdListener(
        onAdLoaded: (ad) {
          setState(() {
            _loadedAds[index] = ad as AdManagerBannerAd;
            _adLoadStatus[index] = true;
          });
        },
        onAdFailedToLoad: (ad, error) {
          debugPrint('Ad failed to load at index $index: $error');
          ad.dispose();
          setState(() {
            _adLoadStatus[index] = false;
          });
        },
      ),
    );

    await ad.load();
  }

  Widget _buildAd(int index) {
    final ad = _loadedAds[index];
    final isLoaded = _adLoadStatus[index] ?? false;

    if (ad != null && isLoaded) {
      return SizedBox(
        width: 320,
        height: 250,
        child: AdWidget(ad: ad),
      );
    }

    return const SizedBox.shrink();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: 50,
        itemBuilder: (context, index) {
          if ((index + 1) % _adFrequency == 0) {
            return _buildAd(index);
          }

          return Container(
            height: 50,
            color: index.isOdd ? Colors.red : Colors.blue,
            alignment: Alignment.center,
            margin: const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
            child: Text(
              'Item ${index + 1}',
              style: const TextStyle(color: Colors.white, fontSize: 18),
            ),
          );
        },
      ),
    );
  }
}

</details> ```

@github-actions github-actions bot removed the feedback required Further information is requested label Jan 15, 2025
@malandr2
Copy link
Collaborator

Hi @memoriasIT, this looks a lot better. I see some lagging around 0:14 - 0:15 but that appears to be with the rows and not the ads.

@memoriasIT
Copy link
Author

memoriasIT commented Jan 15, 2025

I came across this thread with a lot of people having problems with One UI 4.x, so I upgraded the Samsung S20 to 5.1
I don't see a lot of difference in this device from before to now (but in this one the artifacts were already minimal).
I also noticed that it also matters where you touch to scroll. It seems to be worse if you scroll clicking in the ad or in a different item of the list. I guess due to the web view?

I will ask the client (Samsung A51) tomorrow for their One UI version and maybe an upgrade makes it better for them.

Thanks for the help until now by the way :)

Samsung S20 on profile mode:

WhatsApp.Video.2025-01-15.at.19.57.01.1.mp4

@memoriasIT
Copy link
Author

I talked with two colleagues having issues with the ads and having Samsung A51s.
They both have One UI 5.1, so upgrading is not an option.
They also report that they are able to see ad mob in other apps that are native...

I am a bit out of ideas now ☹

@malandr2
Copy link
Collaborator

malandr2 commented Jan 16, 2025

Hi @memoriasIT, considering this only happens on some but not all devices, the issue doesn't appear to be directly related to a feasible action item for the google_mobile_ads flutter plugin. Preloading the banner ads did see improvement in the scrolling performance. With Android, some devices are less performant than others which may affect app behavior. For example, the Samsung A51 is an older device from 2020 and banner ads each contain a webview which are very task-heavy objects.

As far as addressing the banner ad not appearing at all, is that something that has been resolved with preloading the ads?

@malandr2 malandr2 changed the title AdManagerBannerAd flickering and fails to display in Android AdManagerBannerAd flickering and fails to display in Android Samsung Jan 16, 2025
@memoriasIT
Copy link
Author

Unfortunately it does not get fixed with these changes... :(

@malandr2
Copy link
Collaborator

malandr2 commented Jan 17, 2025

I see. For the banner issue of it not appearing, to double check is this reproducible only on certain devices? Or others? If so, can you share the ad request and response from ad inspector so I can take a closer look? To confirm if it is a Flutter issue

@memoriasIT
Copy link
Author

Unfortunately I don't have more android phones to test, but it is reproducible on multiple A51s

I can try to provide more data on Monday

@memoriasIT
Copy link
Author

I just tested on a Samsung A53 with android 14 and One UI: 6.1
It runs fine there. Testing with the ad inspector on the A51 is still on my TODO list, but the phone is not in my possesion and the client is not so technical.

@malandr2 malandr2 added the feedback required Further information is requested label Jan 21, 2025
@memoriasIT
Copy link
Author

memoriasIT commented Jan 27, 2025

We did some investigation with the phone. We discovered that the problem is with the rendering.
Disabling Impeller will make it show the ads, but the Ad Inspector won't show either way, only a black screen will be shown.

Searching for problems on the Flutter SDK will show the issue I recorded on my first video.
flutter/flutter#160804

From the package standpoint I am not sure how much can be solved, perhaps making the Ad Inspector Skia compatible so it can be used on older hardware.
In the Flutter issues you can find multiple devices that will have the problem. Perhaps you have one of these on your possession for testing:

Nice thread with the black screen issue (what I get when opening ad inspector):
flutter/flutter#160201 (comment)

Problems with Web Views with Impeller (Glitches like in the first video I posted here): flutter/flutter#160804 (comment)

Motorola G8 Power Lite
Samsung Galaxy tab s6
Samsung Galaxy note 10 lite
OPPO F11
Samsung Galaxy S6
Samsung Galaxy A51

Some other devices you can find in other issues: flutter/flutter#159834 (comment)

OPPO CPH2043 (Reno 3) flutter/flutter#161144 (comment)
Redmi Note 8T flutter/flutter#159834 (comment)
Nothing Phone 2 (Adreno 730) flutter/flutter#159834 (comment)

@github-actions github-actions bot removed the feedback required Further information is requested label Jan 27, 2025
@malandr2
Copy link
Collaborator

Hi @memoriasIT, thank you for taking a closer look in to this. We also have noticed for some that disabling impeller improves ad rendering #1171 (comment) and that older devices have seen performance issues relative to newer devices.

It's been well documented as you've shared that a lot of these issues are related to the Flutter SDK and not something that the google mobile ads plugin can resolve. I've shared with @LTPhantom that ad inspector is a black screen for your environment.

I think we can close this ticket out as we've identified workarounds for these Flutter SDK limitations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants