googleads / googleads-mobile-flutter

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

Android inline ad performance #269

Closed jjliu15 closed 2 years ago

jjliu15 commented 3 years ago

There have been a number of complaints about performance of inline banner and native ads on Android:

As mentioned in https://github.com/googleads/googleads-mobile-flutter/issues/80#issuecomment-803621668, performance is noticeably worse on Android 9 and below. This is related to use of hybrid composition, which is a requirement due to technical constraints.

Currentworkarounds are to constrict inline ads to android 10 and above, or only to only use fixed position banner/native ads.

svprdga commented 3 years ago

Not show inline ads to android < 10 is a disaster from a business perspective, we are talking of thousands of users.

@jjliu15 does this same plugin support the fixed position banners you are talking about (just like the deprecated plugin did)?

jjliu15 commented 3 years ago

Fixed position banners are supported, but the implementation is different than before. Now you need to align the flutter widget that displays the banner ad to a fixed position. You can see the example app for a reference

svprdga commented 3 years ago

Thanks @jjliu15

I have tried the solution proposed here and it works perfect. I don't know the implementation details that this user did but, but maybe here we have a possible solution to the problem.

colbymaloy commented 3 years ago

Sadly this doesnt do much for me. Using A stack with InteractiveViewer and a bottom aligned banner ad, my frame time is 1000ms on an IpadPro 12.9inch.

blasten commented 2 years ago

We have added a flag to the Flutter master channel that helps improve the performance.

It's not a perfect fix since the Ad may be a few frames behind the Flutter frame, but depending on the layout you use, it could be useful.

Please try it out, and let us know if the performance is improved.

To use this flag, set PlatformViewsService.synchronizeToNativeViewHierarchy(false). For example:

import 'package:flutter/services.dart';

void main() {
   PlatformViewsService.synchronizeToNativeViewHierarchy(false);
   runApp(MyApp());
}
sleepingkit commented 2 years ago

We have added a flag to the Flutter master channel that helps improve the performance.

It's not a perfect fix since the Ad may be a few frames behind the Flutter frame, but depending on the layout you use, it could be useful.

Please try it out, and let us know if the performance is improved.

To use this flag, set PlatformViewsService.synchronizeToNativeViewHierarchy(false). For example:

import 'package:flutter/services.dart';

void main() {
   PlatformViewsService.synchronizeToNativeViewHierarchy(false);
   runApp(MyApp());
}

I am in master branch but didn't see this method. The method 'synchronizeToNativeViewHierarchy' isn't defined for the type 'PlatformViewsService'.

Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel master, 2.4.0-5.0.pre.140, on macOS 11.4 20F71 darwin-arm, locale zh-HK) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.3) ✗ cmdline-tools component is missing Run path/to/sdkmanager --install "cmdline-tools;latest" See https://developer.android.com/studio/command-line for more details. ✗ Android license status unknown. Run flutter doctor --android-licenses to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/macos#android-setup for more details. [✓] Xcode - develop for iOS and macOS [✓] Chrome - develop for the web [✓] Android Studio (version 4.2) [✓] VS Code (version 1.57.1) [✓] Connected device (3 available)

! Doctor found issues in 1 category.

blasten commented 2 years ago

@sleepingkit You may need to run flutter upgrade after changing the channel.

https://github.com/flutter/flutter/blob/e82a69a95e8ea3a4617d6fb3f89b21ee227cb96b/packages/flutter/lib/src/services/platform_views.dart#L192

svprdga commented 2 years ago

Hi @blasten, I have performed some tests:

Stable branch

stable-branch

Master branch with synchronizeToNativeViewHierarchy to false

with-flag-true

I think that the performance is a little bit worse in the master branch with this flag.

I have also performed the same test with this fork:

fork

The author of this fork says here that he's using AndroidView, is there any reason why this solution is not applied to this plugin?

blasten commented 2 years ago

@svprdga that doesn’t seem right. It can’t possibly be more expensive, since there’s less work.

We also enable thread merging, which is the other thing that reduces performance.

Normally in a Flutter app, there is a raster thread and a platform/Android main UI thread. When we show an Android view, we are unable to continue with this thread configuration due to the dependencies and constraints. For example, you cannot add a view to an Android app from a different thread, doing so is prohibited.

Would you be willing to share your app, and I can profile it further?

naamapps commented 2 years ago

@blasten Why is everyone ignoring this fork https://github.com/googleads/googleads-mobile-flutter/issues/80#issuecomment-797510235? It is obviously a good solution to the performance issues. Please, give a reason to why not merge it to the package and also why every contributor is ignoring it. Thanks

svprdga commented 2 years ago

@blasten I can't share the app, but I have recreated the issue in this sample project. (*) Remember to set your app ID in AndroidManifest

Stable branch

stable-branch

Master branch

master-branch

I'd say that has improved a little bit, but far from being efficient. The UI I have created is extremely simple, with a more complex UI the performance is worse.

blasten commented 2 years ago

@naamapps we aren't. We used that approach initially, but hit technical limitations - hybrid composition workarounds those limitations.

Stay tuned for future improvements.

naamapps commented 2 years ago

@blasten It's great to hear that the development is active and you're trying to make the package better. Another question I had and I opened an issue on it #313. Is there a reason this package uses native views (which are expensive and have a lot of performance issues) instead of actually using flutter widgets?

svprdga commented 2 years ago

@blasten I am right now using the fork in many apps, around 10k users combined, without any issue. I can't say the same regarding the official package (I had to quickly replace it once I realized how bad the performance was). Can you elaborate more on which are these technical limitations? Thank you.

bdlukaa commented 2 years ago

Can you elaborate more on which are these technical limitations?

I think the reason is because AndroidView (virtual display) performs the click programmatically, which isn't allowed by admob.

svprdga commented 2 years ago

Thanks for the clarification @bdlukaa .

If this is the case, then we have to decide between:

Perfect.

atrope commented 2 years ago

Only to add to the discussion, In our app we restrict some models(via Remote Config) because of degraded performance.

Those days I Was also thinking how to provide a better experience for the user and then those ideas came:

1.- Inject the JS code inside a Webview. This worked, but had the same "problem" as the current implementation because inappwebview uses Android View as well - https://inappwebview.dev/docs/in-app-webview/basic-usage/

2 - Make a Dart solution fetching the ad from Admanager and firing all the needed callbacks (This sound the best solution but comes with caveats that we can't bear like no Viewability Tracking, no Open Bidding, no AdX etc) - https://support.google.com/admanager/answer/2623168?hl=en Maybe the ads team can help us and we can remake this plugin 100% in dart(at least for banners?)

If anyone thinks on a better solutions we can try to implement so we can check performance-wise if it would be ok :)

naamapps commented 2 years ago

@atrope a 100% dart solution is what we need I think. Webviews and native views are not performant in flutter, so making actual widgets and having the logic in dart is what will make the package complete.

bdlukaa commented 2 years ago

@atrope recently I've been thinking of creating a startup called "Flutter Ads" or something like that, that provides ads and has a full-dart implementation, but I lost interest on it. I'll leave this idea here in case of someone wants to work on it.

atrope commented 2 years ago

Hey guys I made here something so we can check performance for the loaded banners using somewhat native requests..

DO NOT USE THIS TO REQUEST ADS in your Test/Prod App, it has none of the requirements for it.

Be sure to have House Simple ads so it can fetch something as it does not work for dynamic allocation nor adx.

it uses flutter_html to parse the html returned by dfp and dio for request. so include it in your project:

  dio: ^4.0.0
  flutter_html:
    git:
      url: https://github.com/Sub6Resources/flutter_html

import 'dart:math';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_html/flutter_html.dart';

class BannerTest extends StatefulWidget {
  const BannerTest({
    Key? key,
    required this.adUnit,
    required this.sizes,
  }) : super(key: key);
  final String adUnit;
  final List<String> sizes;

  @override
  State<BannerTest> createState() => _BannerTestState();
}

class _BannerTestState extends State<BannerTest> {
  String? data;
  @override
  void initState() {
    super.initState();
    final params = {
      'iu': widget.adUnit,
      'sz': widget.sizes.join('%7c'),
      'c': Random().nextInt(429497629),
      'tile': Random().nextInt(429497629)
    }.entries.map((e) => '${e.key}=${e.value}').toList().join('&');

    final url = 'https://securepubads.g.doubleclick.net/gampad/adx?$params';

    final headers = {
      'User-Agent':
          'Mozilla/5.0 (Linux; Android 11) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.115 Mobile Safari/537.36',
    };
    Dio().get(url, options: Options(headers: headers)).then((value) {
      setState(() {
        data = value.data as String;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return data == null ? Container() : Html(data: data!);
  }
}

Call the banner anywhere with

BannerTest(
             adUnit: adUnit,
            sizes: const ['320x50', '320x100'],
          )

Send here the performance results :)

jangruenwaldt commented 2 years ago

Thanks for the clarification @bdlukaa .

If this is the case, then we have to decide between:

  • Comply with AdMob policy, use the official package, and provide a bad experience for those users who don't have the luck to have a powerful device; which will eventually lead to bad reviews, a drop in user acquisition, losing this mass of users and basically reduce the revenue income dramatically.
  • Don't comply with the policy, use another plugin to provide the expected smooth experience, and then being exposed to sanctions or account suspensions.

Perfect.

Wow, that sums it up so well. Ads are extremely important for devs. Please Flutter Team, put some focus on this!

This is quite a bottleneck for flutter applications. Many many people would really appreciate it. We can not realistically write this ad library ourselves.

atrope commented 2 years ago

Hey Guys, Do you think a 100% dart option requesting the ads would be doable? I Ask because we would need support from the GAM Team but it should not be a complicated solution to implement if they support it :)

bdlukaa commented 2 years ago

@atrope IMO it'd be the best option. Most Android developers are now using Flutter as their main tool to develop apps (according to Jetbrains), and it's frustating to not have ads on it.

tho, in a dart option, it'd be pretty easy to use ads on other platforms instead of mobile.

atrope commented 2 years ago

For those wanting to try the option PlatformViewsService.synchronizeToNativeViewHierarchy(false) I Added in my fork the useHybridComposition property that goes back to using PlatformViewLink instead of AndroidView.

We will ship next week with this option enabled via remote config and will check the app performance.

You should do something like this:

  if (Platform.isAndroid) {
    androidInfo = await DeviceInfoPlugin().androidInfo;
    final isAndroidOld = (androidInfo.version.sdkInt ?? 0) < 29; //Android 10
    useHybridComposition = remoteConfig.getBool(
      isAndroidOld
          ? RemoteConfigKey.useHybridCompositionOlderOS
          : RemoteConfigKey.useHybridCompositionNewerOS,
    );
    if (isAndroidOld && useHybridComposition) {
      await PlatformViewsService.synchronizeToNativeViewHierarchy(false);
    }
  }

And of course in the AdWidget:


AdWidget(
                    ad: _banner!,
                    useHybridComposition: true,
                  )

What I've already seen is that using Hybrid Composition makes the ads "float"(I Guess that's what @blasten meant by lag) while scrolling, here is an example:

https://user-images.githubusercontent.com/2945478/133845019-9567e59d-8b96-4591-952d-dc9e42a728ba.mp4

Also, when navigating to another screen or going back from another page, the banner clearly stays on top until it is destroyed.

https://user-images.githubusercontent.com/2945478/133845402-59dc7e86-b1aa-4f1b-a48d-653a13be19c6.mp4

namchuai commented 2 years ago
Also, when navigating to another screen or going back from another page, the banner clearly stays on top until it is destroyed.

I face the same issue. It's very easy to see on Android with default activity exit animation.

stjfk commented 2 years ago

I wouldn't expect such a bug in such an important plugin. It is not possible to scroll while ads are active.

sleepingkit commented 2 years ago

Is it going to be fixed? This issue seriously affects my apps so long.

dev-ltk commented 2 years ago

Not only on android, same happens on ios which you can experience significant frame drop when the ad is showed.

dayron9110 commented 2 years ago

News?

jangruenwaldt commented 2 years ago

Honestly giving up on this. It never seemed to me like there was any real interest in this topic by the maintainers.

My app would be a lot better with lag-free native ads, but I dont see it happening in less than 2 years. Major disadvantage of flutter. :(

AnthonyH7386 commented 2 years ago

The @atrope fork is a massive improvement for me however when the ads are displayed on a page with a Google Map then all hell breaks loose. The app grinds to a halt and becomes unresponsive after a minute or so.

svprdga commented 2 years ago

For those having issues, I'm using this fork for some months now and it works great; but for some reason, its solution is not applied to the official plugin. Given that this is an open-source project, I would appreciate more transparency from the maintainers regarding what's going on with this matter.

atrope commented 2 years ago

@svprdga there are reasons the team already explained why they are using now PlatformViewLink instead of AndroidView. In my app I am using my fork on the branch feature/suamusica. I Always keep it updated with current master of the plugin so you can use without worries.

The real Upgrade here would be to have a 100% Dart solution that would not involve platform views. I Already sent here an example using the "Tagless request" from GAM Docs but it has massive Unsupported features as I noted here: https://github.com/googleads/googleads-mobile-flutter/issues/269#issuecomment-887507743

It can only be doable if the team work with GAM because the current solution does not work for majority of us that need AdX,ActiveView, Dynamic Allocation etc..

Again if we were able to request directly from Dart, i would gladly help to code the plugin as needed.

bdlukaa commented 2 years ago

@atrope I would gladly help to code it as well. Not having ads in flutter is one of its major disadvantages.

erperejildo commented 2 years ago

using google_mobile_ads: ^1.0.1 ads are fine on iOS but extremely slow on Android. Both banners and native reduce the fps. I had to move to this other package since this performance is something I've been facing for a while: https://pub.dev/packages/native_admob_flutter/example

rocketman7 commented 2 years ago

It's really astonishing that the official team has done NOTHING on this. Why the heck did you guys release this official package and do NOTHING even this issue has been for almost a YEAR. AND it's not only Android issue but iOS as well. Especially, when native ads are inside a listView, it almost blows the app. What a team doing nothing on the most critical problem on this OFFICIAL PACKAGE!! Claps for you guys :)

rocketman7 commented 2 years ago

using google_mobile_ads: ^1.0.1 ads are fine on iOS but extremely slow on Android. Both banners and native reduce the fps. I had to move to this other package since this performance is something I've been facing for a while: https://pub.dev/packages/native_admob_flutter/example

This package doesn't seem to support iOS for Native Ads, does it?

erperejildo commented 2 years ago

tbh I haven't tried it. I tried to use native ads because of this issue. I thought native ads were fine. So with that package I use banner for both, which I find simpler to implement

jangruenwaldt commented 2 years ago

It's really astonishing that the official team has done NOTHING on this. Why the heck did you guys release this official package and do NOTHING even this issue has been for almost a YEAR. AND it's not only Android issue but iOS as well. Especially, when native ads are inside a listView, it almost blows the app. What a team doing nothing on the most critical problem on this OFFICIAL PACKAGE!! Claps for you guys :)

Yeah this is so demoralizing. They just dont even care to make their plugins usable. They just want to put out anything so they can claim Flutter supports ads.

davidgalarza commented 2 years ago

I love Flutter, but this is so frustrating.

rocketman7 commented 2 years ago

It's really astonishing that the official team has done NOTHING on this. Why the heck did you guys release this official package and do NOTHING even this issue has been for almost a YEAR. AND it's not only Android issue but iOS as well. Especially, when native ads are inside a listView, it almost blows the app. What a team doing nothing on the most critical problem on this OFFICIAL PACKAGE!! Claps for you guys :)

@blasten @jjliu15 Can we get at least your team's thought or so called feedback on this? Any PLAN or EXCUSES?? Or you're just ignoring all these issues?? It's the most critical issue considering how Admob is crucial for app developer and environment. Should we all just wait for another year or two??? SERIOUSLY!

naamapps commented 2 years ago

Flutter needs a stable, fast and reliable way to monetize apps and this package ain't it. The only way to fix this is to implement ads with pure dart, without native views (https://github.com/googleads/googleads-mobile-flutter/issues/313)

The team needs to communicate and answer our concerns, because if they don't they might as well didn't make this package open source.

We can't do it on our own, only google can implement a pure dart solution. But they are ignoring this issue for a year, either because they don't care, or either because they can't/don't want to do anything about it. It really seems like this package is abandoned!

I really hope that I'm wrong and there are plans to fix this package, but when there are no words from the team and they keep ignoring us, it's hard to be optimistic.

rocketman7 commented 2 years ago

The team is bloody irresponsible. No one posts any feedback. You guys better take off that 'collaborator' title. You're just insulting the project. Consider how damn long time has been since the first issue on Native and Banner Ad. 'Irresponsible' is all we can give to this team. Remember how many times this package was mentioned as an Google Official package for Google Admob in damn bloody announcement clips, live shows and articles by Google Flutter team. @maheshmnj @jjliu15

naamapps commented 2 years ago

How no one from the team replied yet?? Super unprofessional and a red flag for newcomers.

Unfortunately I'm stuck with flutter since I chose to develop my app with it without knowing there are no reliable solutions for ads. And I can't publish it without a stable and reliable ads solution!

What can we do to get the team's attention? We are only asking for a simple update on the situation.

Please communicate!!

erperejildo commented 2 years ago

The team is bloody irresponsible. No one posts any feedback. You guys better take off that 'collaborator' title. You're just insulting the project. Consider how damn long time has been since the first issue on Native and Banner Ad. 'Irresponsible' is all we can give to this team. Remember how many times this package was mentioned as an Google Official package for Google Admob in damn bloody announcement clips, live shows and articles by Google Flutter team. @maheshmnj @jjliu15

To me this can be the most important package for Flutter. If we me make apps the main goal is always the same: make money. If the only official package for that is this this should be their focus.

I posted this few comments above but in case someone is facing any issue better moving to this other option: https://pub.dev/packages/native_admob_flutter/example

If you want to try it out without implementing anything you can check my app (create an account for free): https://play.google.com/store/apps/details?id=com.drodriguez.my_rents

when the banner is displayed open and close the sidebar

rocketman7 commented 2 years ago

Fun Facts!

  1. The whole thread related to this issue started almost a year ago. (never fixed)
  2. This thread started on Jun of this year (6 months ago) (of course, never fixed)
  3. I started filing the issues and comments aggressively 7 days ago on here Github, Flutter official Twitter, and Youtube Flutter channel, but damn NO ONE replied.

Collaborators have eventually postponed it to the year-end, so they can be freely making excuses for not doing anything because it's holiday season! Congrats you guys!! You finally made it! So proud of you, dudes. Happy Holidays!

@jjliu15 @maheshmnj

erperejildo commented 2 years ago

Fun Facts!

  1. The whole thread related to this issue started almost a year ago. (never fixed)
  2. This thread started on Jun of this year (6 months ago) (of course, never fixed)
  3. I started filing the issues and comments aggressively 7 days ago on here Github, Flutter official Twitter, and Youtube Flutter channel, but damn NO ONE replied.

Collaborators have eventually postponed it to the year-end, so they can be freely making excuses for not doing anything because it's holiday season! Congrats you guys!! You finally made it! So proud of you, dudes. Happy Holidays!

@jjliu15 @maheshmnj

I have another app which is a board game. The season with more downloads is specially Xmas. The risk for me is really high because I only need one player (it's a game with few teams) complaining and suggesting something else. So instead of having 15 people playing I can have 0.

We all understand code complications but at least they should provide some feedback: why is this taking so long, what are the plans and possible fix date, etc. I complained here about documentation already on a different topic: https://github.com/flutter/flutter/issues/94977#issuecomment-990935092

"Stay tuned for future improvements" is not enough for us I'm afraid if we still tuned and you guys don't provide any improvements.

bdlukaa commented 2 years ago

This is funny. This is an issue with the Flutter Framework. This not only happens to this plugin, but to google maps and webview as well.

You guys complain everyday here with the admob team when you guys should be complaining with the Flutter Team itself. There are several open issues about platform-views (sort by thumbs up):

https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22a%3A+platform-views%22+sort%3Areactions-%2B1-desc+performance

naamapps commented 2 years ago

@bdlukaa While you are right that there is an issue with flutter in general, we also complain about the team not responding and also not transparent about future plans (pure dart ads potentially).

rocketman7 commented 2 years ago

This is funny. This is an issue with the Flutter Framework. This not only happens to this plugin, but to google maps and webview as well.

You guys complain everyday here with the admob team when you guys should be complaining with the Flutter Team itself. There are several open issues about platform-views (sort by thumbs up):

https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22a%3A+platform-views%22+sort%3Areactions-%2B1-desc+performance

If so, how your package could avoid the lags that all PlatformView can possibly bring? And why can't this team do the same or better thing even it is highly recommended by the official Flutter team?