This Dart package will utilize the plugin, google_mobile_ads, so to quickly and easily implement ads into a Flutter app.

Related tags

Open Source Apps ads
Overview

Add Ads to your App in a Snap!

Medium Pub.dev GitHub stars

This Dart package will utilize the plugin, google_mobile_ads, so to quickly and easily implement ads into a Flutter app.

Installing

I don't always like the version number suggested in the 'Installing' page. Instead, always go up to the 'major' semantic version number when installing my library packages. This means always entering a version number trailing with two zero, '.0.0'. This allows you to take in any 'minor' versions introducing new features as well as any 'patch' versions that involves bugfixes. Semanitic version numbers are always in this format: major.minor.patch.

  1. patch - I've made bugfixes
  2. minor - I've introduced new features
  3. major - I've essentially made a new app. It's broken backwards-compatibility and has a completely new user experience. You won't get this version until you increment the major number in the pubspec.yaml file.

And so, for this version, add this to your package's pubspec.yaml file instead:

dependencies:
  ads:^3.0.0

Sign Up and Get Your ID’s

First and foremost, you have to sign up for AdMob. Please, turn to AdMob Help for further guidance on this. You’re going to have to go to your Google AdMob Dashboard and get your id’s as well. There’s the ‘app ID’ used to identify your individual app, and there’s individual unit ID’s unique to each ‘type’ of ad you decide to use. Currently, there are three types: a Banner ad, an Interstitial ad, and a Video ad. Might as well do all that now, and then come back here to learn how to display such ads in your Flutter app. GoogleAdMob

It’s A Test. Not For Real

Note, test id’s are supplied by the plugin to be used during development. Using your own id would violate ‘AdMob by Google’ policy. You can’t be clicking ads on your own app. They’ll know.

For Android, Modify AndroidManifest.xml

A common error you may encounter when trying this package out is Google complaining that the AdMob was not properly initialized. Merely follow the directions below to resolve this: androidManifest

For iOS, Update your Info.plist

Info.plist and add Info plist

Your App's Analytics in Ads

So, you created an AdMob account in order to monetize with ads in your production app. However, the kind of ads displayed will get a little help if you assign a Firebase project to your app as well. In fact, it's been suggested to be an esstential step, Missing setup steps in readme. This is yet to be confirmed however. Regardless, turn to the links below to add Firebase to your app: Add Firebase to your iOS project and Add Firebase to your Android project FirebaseToiOS FirebaseToAndroid

failed to load ad : 3

errorLoadAd03 Google simply isn't ready for you. It doesn't have any ads to give you yet. Patience is a virtue. The only errors I consistently receive from users are not of the Dart package itself, but are due to Google. Once the user has registered with Google, a common complaint is there’s still only ‘test’ ads being displayed, but that’s because it’ll take some hours if not a day to receive production ads. Wait a day, and see for yourself.

Mitigate Error 3 with Mediation

And so the error is expected if there is little or no ad available to you. It's a No Fill Error. I'm told, to help mitigate such an error, however, you can try setting up Mediation in your Admob account--to get ads to your apps from multiple sources.

Install Ads as a Package

Dart uses packages to distribute libraries like this one. You can find publicly available packages on the Pub site. The Ads package in particular. ads

There Must Only Be One!

Try instantiating more than one Ads object, and you'll be a little dissappointed if not down right confused. It'll appear the second Ads object is not working, and you'd be right.

    _ads = Ad(
      appId,
      bannerUnitId: bannerUnitId,
      screenUnitId: screenUnitId,
      keywords: <String>['ibm', 'computers'],
      contentUrl: 'http://www.ibm.com',
      childDirected: false,
      testDevices: ['Samsung_Galaxy_SII_API_26:5554'],
      listener: eventListener,
    );

    _adsTest = Ad(
      appId,
      bannerUnitId: bannerUnitId,
      screenUnitId: screenUnitId,
      keywords: <String>['ibm', 'computers'],
      contentUrl: 'http://www.ibm.com',
      childDirected: false,
      testDevices: ['Samsung_Galaxy_SII_API_26:5554'],
      listener: eventListener,
    );

The Google plugin is designed to work with one app and its set of ads. That's all. Creating another Ads object will serve no purpose for you because the Ads Dart package will be aware of the first one and work only with that one. Note, they'll be no 'error message' or notification there's more than one Ads object. The Dart package is designed not to be that disruptive in development or in production. The second object will just not do anything. It simply won't work, and will record the reason why in the log files. That's all.

Keep It Static

A means to have access to the Ads instance from 'anywhere' in our app would be to have it all contained in a static ulitity class. Below only the showBannerAd() and dispose() functions are implemented, but you'll get the idea and should able to implement any and all the functions you require:

AppAds.dart

keywords, String contentUrl, bool childDirected, List testDevices, bool testing, MobileAdListener listener, State state, double anchorOffset, AnchorType anchorType}) => _ads?.showBannerAd( adUnitId: adUnitId, size: size, keywords: keywords, contentUrl: contentUrl, childDirected: childDirected, testDevices: testDevices, testing: testing, listener: listener, state: state, anchorOffset: anchorOffset, anchorType: anchorType); static void hideBanner() => _ads?.closeBannerAd(); /// Call this static function in your State object's initState() function. static void init() => _ads ??= Ads( _appId, bannerUnitId: _bannerUnitId, keywords: ['ibm', 'computers'], contentUrl: 'http://www.ibm.com', childDirected: false, testDevices: ['Samsung_Galaxy_SII_API_26:5554'], testing: false, listener: _eventListener, ); /// Remember to call this in the State object's dispose() function. static void dispose() => _ads?.dispose(); }">
class AppAds {
  static Ads _ads;

  static final String _appId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544~3347511713'
      : 'ca-app-pub-3940256099942544~1458002511';

  static final String _bannerUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/6300978111'
      : 'ca-app-pub-3940256099942544/2934735716';

  /// Assign a listener.
  static MobileAdListener _eventListener = (MobileAdEvent event) {
    if (event == MobileAdEvent.clicked) {
      print("_eventListener: The opened ad is clicked on.");
    }
  };

  static void showBanner(
          {String adUnitId,
          AdSize size,
          List<String> keywords,
          String contentUrl,
          bool childDirected,
          List<String> testDevices,
          bool testing,
          MobileAdListener listener,
          State state,
          double anchorOffset,
          AnchorType anchorType}) =>
      _ads?.showBannerAd(
          adUnitId: adUnitId,
          size: size,
          keywords: keywords,
          contentUrl: contentUrl,
          childDirected: childDirected,
          testDevices: testDevices,
          testing: testing,
          listener: listener,
          state: state,
          anchorOffset: anchorOffset,
          anchorType: anchorType);

  static void hideBanner() => _ads?.closeBannerAd();

  /// Call this static function in your State object's initState() function.
  static void init() => _ads ??= Ads(
        _appId,
        bannerUnitId: _bannerUnitId,
        keywords: <String>['ibm', 'computers'],
        contentUrl: 'http://www.ibm.com',
        childDirected: false,
        testDevices: ['Samsung_Galaxy_SII_API_26:5554'],
        testing: false,
        listener: _eventListener,
      );

  /// Remember to call this in the State object's dispose() function.
  static void dispose() => _ads?.dispose();
}

Simply import the Dart file, AppAds.dart, in this case to any library file you would need access to the Ads for one reason or another, and you're on your way.

There's An Article On This

There is an extensive article about this Dart package available on medium.com: Add Ads To Your App in a Snap!

admobFlutter03

How it works

appCodeSample gist: AdMobAdsExample.dart

['ibm', 'computers'], contentUrl: 'http://www.ibm.com', childDirected: false, testDevices: ['Samsung_Galaxy_SII_API_26:5554'], testing: false, listener: eventListener, ); appAds.setVideoAd( adUnitId: videoUnitId, keywords: ['dart', 'java'], contentUrl: 'http://www.publang.org', childDirected: true, testDevices: null, listener: (RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) { print("The ad was sent a reward amount."); setState(() { _coins += rewardAmount; }); }, ); appAds.showBannerAd(); } @override void dispose() { appAds.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('AdMob Ad Examples'), ), body: SingleChildScrollView( child: Center( child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ RaisedButton( key: ValueKey ('SHOW BANNER'), child: const Text('SHOW BANNER'), onPressed: () { appAds.showBannerAd(state: this, anchorOffset: null); }), RaisedButton( key: ValueKey ('REMOVE BANNER'), child: const Text('REMOVE BANNER'), onPressed: () { appAds.hideBannerAd(); }), RaisedButton( key: ValueKey ('SHOW INTERSTITIAL'), child: const Text('SHOW INTERSTITIAL'), onPressed: () { appAds.showFullScreenAd(state: this); }, ), RaisedButton( key: ValueKey ('SHOW REWARDED VIDEO'), child: const Text('SHOW REWARDED VIDEO'), onPressed: () { appAds.showVideoAd(state: this); }, ), Text( "You have $_coins coins.", key: ValueKey ('COINS'), ), ].map((Widget button) { return Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: button, ); }).toList(), ), ), ), ), ); } }">
import 'package:flutter/material.dart';
import 'dart:io' show Platform;
import 'package:firebase_admob/firebase_admob.dart';

import 'package:ads/ad.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Ads appAds;
  int _coins = 0;

  final String appId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544~3347511713'
      : 'ca-app-pub-3940256099942544~1458002511';

  final String bannerUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/6300978111'
      : 'ca-app-pub-3940256099942544/2934735716';

  final String screenUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/1033173712'
      : 'ca-app-pub-3940256099942544/4411468910';

  final String videoUnitId = Platform.isAndroid
      ? 'ca-app-pub-3940256099942544/5224354917'
      : 'ca-app-pub-3940256099942544/1712485313';

  @override
  void initState() {
    super.initState();

    /// Assign a listener.
    var eventListener = (MobileAdEvent event) {
      if (event == MobileAdEvent.opened) {
        print("eventListener: The opened ad is clicked on.");
      }
    };

    appAds = Ad(
      appId,
      bannerUnitId: bannerUnitId,
      screenUnitId: screenUnitId,
      keywords: <String>['ibm', 'computers'],
      contentUrl: 'http://www.ibm.com',
      childDirected: false,
      testDevices: ['Samsung_Galaxy_SII_API_26:5554'],
      testing: false,
      listener: eventListener,
    );

    appAds.setVideoAd(
      adUnitId: videoUnitId,
      keywords: ['dart', 'java'],
      contentUrl: 'http://www.publang.org',
      childDirected: true,
      testDevices: null,
      listener: (RewardedVideoAdEvent event,
          {String rewardType, int rewardAmount}) {
        print("The ad was sent a reward amount.");
        setState(() {
          _coins += rewardAmount;
        });
      },
    );

    appAds.showBannerAd();
  }

  @override
  void dispose() {
    appAds.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('AdMob Ad Examples'),
        ),
        body: SingleChildScrollView(
          child: Center(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                RaisedButton(
                    key: ValueKey<String>('SHOW BANNER'),
                    child: const Text('SHOW BANNER'),
                    onPressed: () {
                      appAds.showBannerAd(state: this, anchorOffset: null);
                    }),
                RaisedButton(
                    key: ValueKey<String>('REMOVE BANNER'),
                    child: const Text('REMOVE BANNER'),
                    onPressed: () {
                      appAds.hideBannerAd();
                    }),
                RaisedButton(
                  key: ValueKey<String>('SHOW INTERSTITIAL'),
                  child: const Text('SHOW INTERSTITIAL'),
                  onPressed: () {
                    appAds.showFullScreenAd(state: this);
                  },
                ),
                RaisedButton(
                  key: ValueKey<String>('SHOW REWARDED VIDEO'),
                  child: const Text('SHOW REWARDED VIDEO'),
                  onPressed: () {
                    appAds.showVideoAd(state: this);
                  },
                ),
                Text(
                  "You have $_coins coins.",
                  key: ValueKey<String>('COINS'),
                ),
              ].map((Widget button) {
                return Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16.0),
                  child: button,
                );
              }).toList(),
            ),
          ),
        ),
      ),
    );
  }
}

Beta You Bet!

As of this writing, firebase_admob, is still in beta. As such, Banner ads can only be positioned at the top or the bottom of the screen, animation is limited, the ads come in a infinite set of sizes. Lastly, 'native ads' (i.e. ads displayed on UI components native to the platform) are not yet supported.

And the Number of the Counting Shall Be…Three

There are three types of ads currently offered by the firebase_admob plugin. There's the traditional Banner ad, the Interstitial or full-screen ad that covers the interface of their host app when opened, and finally, there's the Video ad that also covers the screen when opened and then returns to the app when closed.

Three types of ads.

It's an Event!

The plugin, firebase_admob, watches for seven separate events when it comes to the Banner ad and the Full-screen ad. Everything from the much-called 'loaded' event to the 'impression' event---which I think fires each if the user has been looking at the ad for so long that the ad itself has refreshed itself. I'm not certain however as there's not much API documentation for this plugin at the time of this writing either.

Below is the the enumerated values currently describing the currently supported events:

Seven events are available to the Banner and Full-screen ad.

With Video ads, there are eight events made available to watch out for. Events are triggered, for example, when the video opens, when the video starts to play, and when the video has completed running. There's also an event that rewards the user for viewing the video.

Eight events associated with a Video.

Listen and Earn!

Since the plugin supplies a whole bunch of events, I've implemented no less than eleven event listeners in this library. The gist provided above lists all the possibles ways to set an event handler on all the types of ads offered by the plugin.

The Banner ad and the FullScreen ad use the same set of 'MobileAdEvent' events while the Video Ad has its own set under the event type, 'RewardedVideoAdEvent'. This means you can break up your event listeners by the type of ad if you want.

Yes, you can assign as many listeners as you want to a particular event. You or someone else can. For example, someone else on your team working on another part of your app may also need to know when an ad is opened.

The Main Event Listener

There is a setter called, eventListener, that you can use to catch 'MobileAdEvent' events. Again, currently there is seven events defined so far and are used by the Banner ad and the Full-Screen (Interstitial) ad.

  appAds.eventListener = (MobileAdEvent event) {
    switch (event) {
      case MobileAdEvent.loaded:
        print("appAds.eventListener: An ad has loaded successfully in memory.");
        break;
      case MobileAdEvent.failedToLoad:
        print("appAds.eventListener: The ad failed to load into memory.");
        break;
      case MobileAdEvent.clicked:
        print("appAds.eventListener: The opened ad was clicked on.");
        break;
      case MobileAdEvent.impression:
        print("appAds.eventListener: The user is still looking at the ad. A new ad came up.");
        break;
      case MobileAdEvent.opened:
        print("appAds.eventListener: The Ad is now open.");
        break;
      case MobileAdEvent.leftApplication:
        print("appAds.eventListener: You've left the app after clicking the Ad.");
        break;
      case MobileAdEvent.closed:
        print("appAds.eventListener: You've closed the Ad and returned to the app.");
        break;
      default:
        print("appAds.eventListener: There's a 'new' MobileAdEvent?!");
    }
  };

Again, you can assign a listener at the init() function and at the 'set' functions---any number of listeners you like. There's functions available to remove these listeners as well of course.

The Banner Listener

The Banner ad has its own setter. You can see below it's called bannerListener.

  appAds.bannerListener = (MobileAdEvent event) {
    switch (event) {
      case MobileAdEvent.loaded:
        print("appAds.bannerListener: An ad has loaded successfully in memory.");
        break;
      case MobileAdEvent.failedToLoad:
        print("appAds.bannerListener: The ad failed to load into memory.");
        break;
      case MobileAdEvent.clicked:
        print("appAds.bannerListener: The opened ad was clicked on.");
        break;
      case MobileAdEvent.impression:
        print("appAds.bannerListener: The user is still looking at the ad. A new ad came up.");
        break;
      case MobileAdEvent.opened:
        print("appAds.bannerListener: The ad is now open.");
        break;
      case MobileAdEvent.leftApplication:
        print("appAds.bannerListener: You've left the app after clicking the Ad.");
        break;
      case MobileAdEvent.closed:
        print("appAds.bannerListener: You've closed the Ad and returned to the app.");
        break;
      default:
        print("appAds.bannerListener: There's a 'new' MobileAdEvent?!");
    }
  };

The Full-Screen Listener

The setter for the Interstitial ad is called screenListener.

  appAds.screenListener = (MobileAdEvent event) {
    switch (event) {
      case MobileAdEvent.loaded:
        print("appAds.screenListener: An ad has loaded successfully in memory.");
        break;
      case MobileAdEvent.failedToLoad:
        print("appAds.screenListener: The ad failed to load into memory.");
        break;
      case MobileAdEvent.clicked:
        print("appAds.screenListener: The opened ad was clicked on.");
        break;
      case MobileAdEvent.impression:
        print("appAds.screenListener: The user is still looking at the ad. A new ad came up.");
        break;
      case MobileAdEvent.opened:
        print("appAds.screenListener: The ad is now open.");
        break;
      case MobileAdEvent.leftApplication:
        print("appAds.screenListener: You've left the app after clicking the Ad.");
        break;
      case MobileAdEvent.closed:
        print("appAds.screenListener: You've closed the Ad and returned to the app.");
        break;
      default:
        print("appAds.screenListener: There's a 'new' MobileAdEvent?!");
    }
  };

The Video Listener

Finally, the setter for the Video ad is called videoListener.

  appAds.videoListener =
      (RewardedVideoAdEvent event, {String rewardType, int rewardAmount}) {
    switch (event) {
      case RewardedVideoAdEvent.loaded:
        print("appAds.videoListener: An ad has loaded successfully in memory.");
        break;
      case RewardedVideoAdEvent.failedToLoad:
        print("appAds.videoListener: The ad failed to load into memory.");
        break;
      case RewardedVideoAdEvent.opened:
        print("appAds.videoListener: The ad is now open.");
        break;
      case RewardedVideoAdEvent.leftApplication:
        print("appAds.videoListener: You've left the app after clicking the Ad.");
        break;
      case RewardedVideoAdEvent.closed:
        print("appAds.videoListener: You've closed the Ad and returned to the app.");
        break;
      case RewardedVideoAdEvent.rewarded:
        print("appAds.videoListener: The ad has sent a reward amount.");
        break;
      case RewardedVideoAdEvent.started:
        print("appAds.videoListener: You've just started playing the Video ad.");
        break;
      case RewardedVideoAdEvent.completed:
        print("appAds.videoListener: You've just finished playing the Video ad.");
        break;
      default:
        print("There's a 'new' RewardedVideoAdEvent?!");
    }
  };

A Event Listener For Every Occasion

This last section provides yet another way to implement a specific event listeners for your ads:

  appAds.banner.loadedListener = () {
    print("appAds.banner.loadedListener: An ad has loaded successfully in memory.");
  };

  appAds.banner.failedListener = () {
    print("appAds.banner.failedListener: An ad failed to load into memory.");
  };

  appAds.banner.clickedListener = () {
    print("appAds.banner.clickedListener: The opened ad is clicked on.");
  };

  appAds.banner.impressionListener = () {
    print("appAds.banner.impressionListener: The user is still looking at the ad. A new ad came up.");
  };

  appAds.banner.openedListener = () {
    print("appAds.banner.openedListener: The ad has opened.");
  };

  appAds.banner.leftAppListener = () {
    print("appAds.banner.leftAppListener: You left the app and gone to the ad's website.");
  };

  appAds.banner.impressionListener = () {
    print("appAds.banner.impressionListener: The user is still looking at the ad. A new ad came up.");
  };

  appAds.banner.closedListener = () {
    print("appAds.banner.closedListener: You've closed an ad and returned to your app.");
  };

  appAds.screen.loadedListener = () {
    print("appAds.screen.loadedListener: An ad has loaded into memory.");
  };

  appAds.screen.failedListener = () {
    print("appAds.screen.failedListener: An ad has failed to load in memory.");
  };

  appAds.screen.clickedListener = () {
    print("appAds.screen.clickedListener: The opened ad was clicked on.");
  };

  appAds.screen.impressionListener = () {
    print("appAds.screen.impressionListener: You've clicked on a link in the open ad.");
  };

  appAds.screen.openedListener = () {
    print("appAds.screen.openedListener: The ad has opened.");
  };

  appAds.screen.leftAppListener = () {
    print("appAds.screen.leftAppListener: The user has left the app and gone to the opened ad.");
  };

  appAds.screen.closedListener = () {
    print("appAds.screen.closedListener: The ad has been closed. The user returns to the app.");
  };

  appAds.video.loadedListener = () {
    print("appAds.video.loadedListener: An ad has loaded in memory.");
  };

  appAds.video.failedListener = () {
    print("appAds.video.failedListener: An ad has failed to load in memory.");
  };

  appAds.video.clickedListener = () {
    print("appAds.video.clickedListener: An ad has been clicked on.");
  };

  appAds.video.openedListener = () {
    print("appAds.video.openedListener: An ad has been opened.");
  };

  appAds.video.leftAppListener = () {
    print("appAds.video.leftAppListener: You've left the app to view the video.");
  };

  appAds.video.closedListener = () {
    print("appAds.video.closedListener: The video has been closed.");
  };

  appAds.video.rewardedListener = (String rewardType, int rewardAmount) {
    print("appAds.video.rewardedListener: The ad was sent a reward amount.");
  };

  appAds.video.startedListener = () {
    print("appAds.video.startedListener: You've just started playing the Video ad.");
  };

  appAds.video.completedListener = () {
    print("appAds.video.completedListener: You've just finished playing the Video ad.");
  };

Add Up Ad Errors

Below is a screenshot of some sample code implementing the error handling available to you when using the Dart package, Ads. By design, any exceptions that may occur in an event listeners' code is caught in a try..catch statement. The goal is to not crash the app for any reason involving AdMob ads. However, if and when an does error occurs, the developer has the means to determine the issue by collecting such errors in the List object, eventErrors. eventError

Other Dart Packages

packages Other Dart packages from the author can also be found at Pub.dev

Comments
  • New versions display only test ads in release mode...

    New versions display only test ads in release mode...

    I recently update the plugin from version 1.0.1 to 1.2 and I have this strange behavior: every ad displayed on device, with the release mode app, is actually a test ad. Same for version 1.1.0, seems only the 1.0.1 maybe check the build mode or the Ads testing: parameter... I don't know.. I tested on 3 version of Android and had the same results..

    opened by SirJohn2024 20
  • onAdFailedToLoad: 3

    onAdFailedToLoad: 3

    I'm getting the following logs on app start in release mode when I load both my interstitial and reward ad (only on Android). I am not doing any of my own printing here, so I'm unsure where they come from.

    W/flutter (12657): onAdFailedToLoad: 3 W/flutter (12657): onRewardedVideoAdFailedToLoad: 3

    Then, when I try to open the rewarded ad, I either get this exception or the onRewardedVideoAdFailedToLoad shown above.

    E/flutter (12657): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: PlatformException(ad_not_loaded, show failed for rewarded video, no ad was loaded, null)
    E/flutter (12657): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:564)
    E/flutter (12657): #1      MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:316)
    E/flutter (12657): <asynchronous suspension>
    E/flutter (12657): #2      _invokeBooleanMethod (package:firebase_admob/firebase_admob.dart:518)
    E/flutter (12657): <asynchronous suspension>
    E/flutter (12657): #3      RewardedVideoAd.show (package:firebase_admob/firebase_admob.dart:392)
    E/flutter (12657): #4      Ads.showVideoAd (package:ads/ads.dart:408)
    E/flutter (12657): #5      AppAds.showVideoAd (package:tabletop_dice/util/app_ads.dart:68)
    E/flutter (12657): #6      MainScreen._buildAppBar.<anonymous closure> (package:tabletop_dice/screens/main_screen.dart:98)
    E/flutter (12657): #7      _PopupMenuButtonState.showButtonMenu.<anonymous closure> (package:flutter/src/material/popup_menu.dart:0)
    E/flutter (12657): #8      _rootRunUnary (dart:async/zone.dart:1132)
    E/flutter (12657): #9      _CustomZone.runUnary (dart:async/zone.dart:1029)
    E/flutter (12657): #10     _FutureListener.handleValue (dart:async/future_impl.dart:126)
    E/flutter (12657): #11     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:639)
    E/flutter (12657): #12     Future._propagateToListeners (dart:async/future_impl.dart:668)
    E/flutter (12657): #13     Future._completeWithValue (dart:async/future_impl.dart:483)
    E/flutter (12657): #14     Future._asyncComplete.<anonymous closure> (dart:async/future_impl.dart:513)
    E/flutter (12657): #15     _rootRun (dart:async/zone.dart:1124)
    E/flutter (12657): #16     _CustomZone.run (dart:async/zone.dart:1021)
    E/flutter (12657): #17     _CustomZone.runGuarded (dart:async/zone.dart:923)
    E/flutter (12657): #18     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:963)
    E/flutter (12657): #19     _microtaskLoop (dart:async/schedule_microtask.dart:41)
    E/flutter (12657): #20     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)
    

    Here is my app_ads.dart wrapper.

    import 'dart:io';
    
    import 'package:ads/ads.dart';
    import 'package:firebase_admob/firebase_admob.dart';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    
    class AppAds {
      static Ads _ads;
    
      static final String _appId =
          Platform.isAndroid ? "my app id" : "";
      static final String _afterRollInterstitialId =
          Platform.isAndroid ? "my interstitial id" : "";
      static final String _removeAdsVideoId =
          Platform.isAndroid ? "my reward id" : "";
    
      /// Call this static function in your State object's initState() function.
      static void init() {
        _ads ??= Ads(
          _appId,
          screenUnitId: _afterRollInterstitialId,
          videoUnitId: _removeAdsVideoId,
          keywords: <String>[
            "technology",
          ],
          childDirected: false,
          testing: kDebugMode,
        );
      }
    
      static void setFullscreenAd({
        AdEventListener listener,
      }) {
        _ads?.setFullScreenAd(
          listener: listener,
        );
      }
    
      static void showFullscreenAd({
        State state,
        double anchorOffset = 0.0,
        AnchorType anchorType = AnchorType.bottom,
      }) {
        _ads?.showFullScreenAd(
          state: state,
          anchorOffset: anchorOffset,
          anchorType: anchorType,
        );
      }
    
      static void setVideoAd({
        VideoEventListener listener,
      }) {
        _ads?.setVideoAd(
          listener: listener,
        );
      }
    
      static void showVideoAd({
        State state,
      }) {
        _ads?.showVideoAd(
          state: state,
        );
      }
    
      /// Remember to call this in the State object's dispose() function.
      static void dispose() => _ads?.dispose();
    
      /// Expose the 'event handling' capabilities to the World as well
      /// Set a Banner Ad Event Listener.
    
      /// Set an Ad Event Listener.
      set eventListener(AdEventListener listener) => _ads?.eventListener = listener;
    
      /// Remove a specific Add Event Listener.
      bool removeEvent(AdEventListener listener) => _ads?.removeEvent(listener);
    
      /// Set an Banner Event Listener.
      set bannerListener(AdEventListener listener) =>
          _ads?.bannerListener = listener;
    
      /// Remove a specific Banner Ad Event Listener.
      bool removeBanner(AdEventListener listener) => _ads?.removeBanner(listener);
    
      /// Set a Full Screen Ad Event Listener.
      set screenListener(AdEventListener listener) =>
          _ads?.screenListener = listener;
    
      /// Remove a Full Screen Ad Event Listener.
      bool removeScreen(AdEventListener listener) => _ads?.removeScreen(listener);
    
      /// Set a Video Ad Event Listener
    //  static set videoListener(VideoEventListenertListener listener) =>
    //      _ads?.videoListener = listener;
    
      /// Remove a specific Video Ad Event Listener.
      static set removeVideo(VideoEventListener listener) =>
          _ads?.removeVideo(listener);
    }
    

    Any ideas? Building for debug mode shows the test interstitial and test reward ad fine. I also have the "Your account is approved. Congratulations! We've verified your account information and your ad serving is enabled." message from Admob, so I don't think it is related to that config. I've double checked all my IDs as well.

    opened by DFreds 19
  • Plugin performance

    Plugin performance

    Hey guys, I'm having problems with your plugin, when I add ads performance of my app drops.

    First thing that I've noticed is that dispose() method needs around 3 seconds to dispose ads and while is doing that its using a lot of resources and apps gets laggy.

    Second thing.. My main screen is a list of news, and when user tap on news he gets navigated to single news page where I want to show banner ad. If I put init() function in initState() of single news page, sometimes it needs a lot of time in order to load banner and if in meantime I navigate back(Navigator.pop) than banner gets stucked in my main page (when it loads), where I dont want it to be, so I put in in main() function of the app, but now scrolling through main screen(list of news) is kinda choppy..

    Please take a look at my code and tell me if I implemented sth wrong or give me some idea how can I optimize code..

     import 'dart:io';
    import 'package:ads/ads.dart';
    import 'package:flutter/material.dart';
    import 'package:firebase_admob/firebase_admob.dart';
    
    class AppAds {
      static Ads _ads;
    
      static final String _appId = Platform.isAndroid
          ? 'ca-app-pub-3940256099942544~3347511713'
          : 'ca-app-pub-3940256099942544~1458002511';
    
      static final String _bannerUnitId = Platform.isAndroid
          ? 'ca-app-pub-3940256099942544/6300978111'
          : 'ca-app-pub-3940256099942544/2934735716';
    
      static void showBanner(
              {String adUnitId,
              AdSize size,
              List<String> keywords,
              String contentUrl,
              bool childDirected,
              List<String> testDevices,
              bool testing,
              State state,
              double anchorOffset,
              AnchorType anchorType}) =>
          _ads?.showBannerAd(
              adUnitId: adUnitId,
              size: size,
              keywords: keywords,
              contentUrl: contentUrl,
              childDirected: childDirected,
              testDevices: testDevices,
              testing: testing,
              state: state,
              anchorOffset: anchorOffset,
              anchorType: anchorType);
    
      static void init() => _ads ??= Ads(
            _appId,
            bannerUnitId: _bannerUnitId,
            childDirected: false,
            nonPersonalizedAds: false,
            size: AdSize.fullBanner,
            testing: true,
            testDevices: ['GSM9X18A11G11457'],
            analyticsEnabled: false,
          );
    
      static void dispose() => _ads?.dispose();
    }
    
    opened by aleksandar-radivojevic 10
  • How to show video in round two ?

    How to show video in round two ?

    first ads is show normally but when end ads and get rewards i'm click round two it not available to load ads

    but i close app and open again it can watch

    opened by athlona64 6
  • Full Screen Ad is not loaded with setFullScreenAd

    Full Screen Ad is not loaded with setFullScreenAd

    First of all, thanks for this great library, it's really helpful.

    I am currently facing an issue. Usually the proper procedure for interstitial Ads, is to load the Ad, make it ready, and when you need to show it, check if it's loaded then show it.

    I assume that the setFullScreenAd method should load the Ad, and showFullScreenAd displays it if loaded.

    currently the behavior is not like that with me, setFullScreenAd does not load the Ad, and only when I use showFullScreenAd the Ad is loaded then displayed, causing the Ad to be delayed, and also unwanted behavior in the app.

    I am not sure if this a problem in my coding (I am new to dart), or a bug in the library, so I appreciate the assistance.

    below are the important parts of my code:

    
    // my static class
    class AppAds {
      static Ads _ads;
      static Function _onScreenCloseHandler = (){};
    
    
    
    //
    ....
    //
    
    static void setFullScreenAd({
        String adUnitId,
        MobileAdTargetingInfo targetInfo,
        List<String> keywords,
        String contentUrl,
        bool childDirected,
        List<String> testDevices,
        bool testing,
        MobileAdListener listener,
        double anchorOffset,
        AnchorType anchorType,
    }) => _ads?.setFullScreenAd(
          adUnitId: adUnitId,
          targetInfo: targetInfo,
          keywords: keywords,
          contentUrl: contentUrl,
          childDirected: childDirected,
          testDevices: testDevices,
          testing: testing,
          anchorOffset: anchorOffset,
          anchorType: anchorType,
          listener: listener,
    );
    
    
    static void showFullScreen({
        String adUnitId,
        MobileAdTargetingInfo targetInfo,
        List<String> keywords,
        String contentUrl,
        bool childDirected,
        List<String> testDevices,
        bool testing,
        MobileAdListener listener,
        double anchorOffset,
        AnchorType anchorType,
        State state,
        Function onClose,
      }) {
      _ads?.showFullScreenAd(
        adUnitId: adUnitId,
          targetInfo: targetInfo,
          keywords: keywords,
          contentUrl: contentUrl,
          childDirected: childDirected,
          testDevices: testDevices,
          testing: testing,
          anchorOffset: anchorOffset,
          anchorType: anchorType,
          state: state,);
    
          _ads.screen.removeClosed(_onScreenCloseHandler);      
          _onScreenCloseHandler = onClose;
          _ads.screen.closedListener = (){
            _onScreenCloseHandler;
          };      
    }
    //
    .....
    //
    
    static void init({bool testing: false, bool childDirected: false }) {
        _ads ??= Ads(
            _appId,
            bannerUnitId: _bannerUnitId,
            screenUnitId: _interstitialId,
            childDirected: childDirected,
            testDevices: _testDevices,
            testing: testing,
            listener: _eventListener,
          );
    
      }
    }
    
    
    
    //main.dart
      MobileAdListener _interstitialEventListener = (MobileAdEvent event) {
               print("=============== InterstitialAd event is $event");
              switch (event) {
                case MobileAdEvent.failedToLoad:
                  Global.adMobInterstitialLoaded = false;    
                  break;
                  
                case MobileAdEvent.loaded:
                  Global.adMobInterstitialLoaded = true;
                  break;
        
                case MobileAdEvent.opened:
                  break;
        
                case MobileAdEvent.closed:
                  Global.adMobInterstitialLoaded = false;
                  AppAds.setFullScreenAd();
                  break;
        
                default:
                  break;
              }
            };
    
        AppAds.init(testing: true, childDirected: false);
        AppAds.setFullScreenAd(listener: _interstitialEventListener);
    
    
    opened by tmrbaset 6
  • iOS simulator?

    iOS simulator?

    I'm trying to get this to work on an iOS simulator but its not clear at all what to use for the testDeivce for this pooch. I get the following in the log but using the value doesn't work:

    To get test ads on this device, set: request.testDevices = @[ kGADSimulatorID ];

    Is there a way to get the actual value of kGADSimulatorID from within Flutter?

    opened by sjmcdowall 6
  • I suspect proguard is breaking ads

    I suspect proguard is breaking ads

    Hello! I've got my test ads all setup and displaying properly in both debug and release mode, but as soon as I build an APK or Appbundle, ads no longer show up and I am unable to debug it. I'm pretty sure Proguard is to blame, but I can't find any exceptions to make. Do you have any advice? Thank you!

    I've tried these to no avail: -keep class com.firebase.** { ; } -keep class org.apache.* { ; } -keepnames class com.fasterxml.jackson.* { ; } -keepnames class javax.servlet.* { ; } -keepnames class org.ietf.jgss.* { ; } -dontwarn org.apache.* -dontwarn org.w3c.dom.** -keep class com.google.ads.** # Don't proguard AdMob classes -keep class com.google.android.gms.ads.** -dontwarn com.google.ads.**

    opened by ThinPotato 5
  • the show local variable is shadowed in showBannerAd() (double declaration)

    the show local variable is shadowed in showBannerAd() (double declaration)

        bool show = false;
        // Can only have one instantiated Ads object.
        if (!_firstObject) return show;
    
        if (_bannerAd == null) {
          bool show = await setBannerAd(
    

    should be:

        bool show = false;
        // Can only have one instantiated Ads object.
        if (!_firstObject) return show;
    
        if (_bannerAd == null) {
          show = await setBannerAd(
    
    
    opened by SirJohn2024 5
  • PlatformException(no_ad_for_id, dispose failed, no ad exists for id=972262985, null)

    PlatformException(no_ad_for_id, dispose failed, no ad exists for id=972262985, null)

    The example code doesn't work when I run the app with initOption 2 or 3, like this: void main() { runApp(MyApp(initOption: 3)); }

    I've got the following exception:

    PlatformException(no_ad_for_id, dispose failed, no ad exists for id=972262985, null)

    id is different every startup

    p.s.: the following example works without any issue: void main() { runApp(MyApp(initOption: 1)); }

    opened by alexacz 5
  • How to close Banner add from different page? Or load Interstitial Ad on Different Page?

    How to close Banner add from different page? Or load Interstitial Ad on Different Page?

    How to close Banner add from different page? Or load Interstitial Ad on Different Page? Given that i can only create one instance? For me now its not doing anything.

    opened by drdDavi 5
  • Need clarification for Ad Unit ID

    Need clarification for Ad Unit ID

    Hello, first of all, this is a great wrapper that you have written.

    I have one confusion though. In the code below for setBanner

    /// Set the Banner Ad options.
      static void setBannerAd({
        AdSize size = AdSize.banner,
        List<String> keywords,
        String contentUrl,
        bool childDirected,
        List<String> testDevices,
        AdEventListener listener,
      }) {
        var info = _targetInfo(
          keywords: keywords,
          contentUrl: contentUrl,
          childDirected: childDirected,
          testDevices: testDevices,
        );
    
        if (listener != null) banner._eventListeners.add(listener);
    
        _bannerAd = BannerAd(
          adUnitId: Ads.testing ? BannerAd.testAdUnitId : Ads._appId,
          size: size,
          targetingInfo: info,
          listener: banner._eventListener,
        );
      }
    

    you are doing this

    adUnitId: Ads.testing ? BannerAd.testAdUnitId : Ads._appId,

    if testing is true you are using BannerAd.testAdUnitId otherwise you are using the _appId that was providences in Ads.init

    Should we not be using a different BannerAdUnitID instead of the _appId?. Or is it ok to use the ApID instead of adUnitID for production app ??

    opened by lab-nit-s 5
  • Ads version 3.0.0 (nullsafe) Video not showing up

    Ads version 3.0.0 (nullsafe) Video not showing up

    Hello there. Just wanted to ask if there is anything new how should we display the video ads in the beta version of the null-safe version?

    This is my code:

    static Future<bool> showRewardAd({required Function userReward, required Function onAdClose}) async {
        return getInstance().setVideoAd(
            show: true,
            testDevices: [],
            childDirected: false,
            adUnitId: AdManager._rewardedAdUnitId,
            contentUrl: 'https://makromapa.pl',
            keywords: <String>['food', 'fit', 'calories'],
            listener: (AdsEvent event, {String? rewardType, int? rewardAmount}) {
              if ([AdsEvent.onAdLoaded, AdsEvent.onAdOpened, AdsEvent.onAppEvent].contains(event)) {
                _logger.d("Reward Ad | Following RewardedVideoAd Event was fired - $event");
                SystemChrome.setEnabledSystemUIOverlays([]);
              }
    
              if (AdsEvent.onRewardedAdUserEarnedReward == event) {
                _logger.i("Reward Ad | User granted reward - $rewardType, ($rewardAmount)");
                userReward();
              }
    
              if (AdsEvent.onAdFailedToLoad == event) {
                _logger.e("Reward Ad | failed to load Reward Ad");
                onAdClose();
              }
    
              if (AdsEvent.onAdClosed == event) {
                _logger.e("Reward Ad | closed");
                onAdClose();
                SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
              }
            })
        .then((value) => getInstance().showVideoAd());
      }
    
    ...
    static Ads getInstance() {
        if (_ads != null) {
          return _ads!;
        }
    
        _ads = Ads(
          trackingId: AdManager._appId,
          videoUnitId: AdManager._rewardedAdUnitId,
          testing: false,
          testDevices: [],
          childDirected: false,
          contentUrl: 'https://example.pl',
          keywords: <String>['test'],
          listener: _eventListener,
        );
    
        return _ads!;
      }
    

    The listener gets with the AdsEvent.onAdLoaded event. There isn't anything else fired. This flow worked on the older version ;

    opened by Marek00Malik 4
  • Can I somehow show a few rewarded ads in a row?

    Can I somehow show a few rewarded ads in a row?

    Is it possible to pre-download a few rewarded ads? As I know, the native SDKs provide such a feature, but I cannot find any information related to this feature in ads documentation

    opened by alectogeek 6
Owner
Andrious Solutions Ltd.
Software Development Solutions Provider
Andrious Solutions Ltd.
A Flutter plugin for the Google Mobile Ads SDK

A Flutter plugin for the Google Mobile Ads SDK

Google Ads 251 Jan 2, 2023
Facebook mediation plugin for Google Mobile Ads (Flutter).

Facebook mediation plugin for Google Mobile Ads Flutter Google Mobile Ads Flutter mediation plugin for Facebook Audience Network. Use this package as

Taeho Kim 4 Nov 14, 2022
The FlexGrid control provides a powerful and quickly way to display data in a tabular format. It is including that frozened column/row,loading more, high performance and better experience in TabBarView/PageView.

flex_grid Language: English| 中文简体 The FlexGrid control provides a powerful and quickly way to display data in a tabular format. It is including that f

FlutterCandies 39 Nov 8, 2022
Quickly generate a personalized WhatsApp link with a predefined message and share it with your audience on your Social Networks!

Quickly generate a personalized WhatsApp link with a predefined message and share it with your audience on your Social Networks!

Sanskar Tiwari 11 Aug 28, 2021
A GUI to quickly manage your WSL2 instances

WSL2 Distro Manager A quick way to manage your WSL2 instances with a GUI. Install This app is available on the Windows Store or as a direct download f

Eric 390 Dec 29, 2022
A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully & easily modifiable.

A package that lets you include a cool, nice looking and validated Password TextFormField in your app to enhance user experience. The package is fully

Muhammad Hamza 21 Jan 1, 2023
Just audio background - A flutter package plugs into just audio to add background playback support and remote controls

just_audio_background This package plugs into just_audio to add background playb

lonyyy 1 Jan 11, 2022
Tooling and libraries for processing dart test output into dev-friendly formats

better_test_reporter Introduction This is an application/library heavily inspired by dart-junitreport and dart-testreport. It takes what was done in t

Betterment 6 Sep 14, 2022
A quick sample app on how to implement a friend list and a profile page in Flutter.

FlutterMates All code resides in the /lib folder: there's no Android / iOS specific code needed. The article, slides and how this came to be, is here.

Codemate Ltd 526 Dec 29, 2022
This is an example of how to implement In-App Reviews on your app.

in_app_review A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if

Thomas Viana 1 Dec 31, 2022
A sample app that implement Uncle Bob's Clean Architecture in Flutter

Clean Architecture for Flutter This a sample app that implement Uncle Bob's Clea

Mahmoud Saeed 28 Nov 8, 2022
Flutter plugin that allows users to create TextAvatar easily!

Colorize Text Avatar Colorize Text Avatar is a package to generate avatar based on your user initials. It supports to generate avatars based on your s

Deniz Çolak 17 Dec 14, 2022
BankGit helps you manage your account and transactions more efficiently by breaking your account into branches for various purposes and then making transactions directly from them.

Bank Git Web Hosted Here : https://bank-management-45848.web.app/ Bank Git is an application built with Flutter and Firebase to help you manage your b

Yash Johri 27 Dec 26, 2022
Caching with flutter riverpod and looking into future providers. Example to demonstrate stale while revalidate pattern.

FLUTTER SWR EXAMPLE Test stale-while-revalidate pattern with riverpod. Look; query_provider package Backend calls are made with ghibli-api Tested Prov

Dipesh Dulal 7 Jun 30, 2022
Tubles is a simple applications to provide any tubles in in google maps and we as the user can navigate into the selected tubles location.

Tubles Tubles is a simple applications to provide any tubles place in google maps and we as the user can navigate into the selected tubles location. F

Yusril Rapsanjani 78 Jan 8, 2023
🎵 Elegant music app to play local music & YouTube music. Distributes music into albums & artists. Has playlists & lyrics.

Harmonoid Elegant music app to play local music & YouTube music. Download Now ?? Feel free to report bugs & issues. We'll be there to fix. Loving the

Harmonoid 2.5k Dec 30, 2022
🎵 Elegant music app to play local music & YouTube music. Distributes music into albums & artists. Has playlists & lyrics. Windows + Linux + Android.

Harmonoid Elegant music app to play local music & YouTube music. Download Now ?? Windows, Linux & Android. Feel free to report bugs & issues. Loving t

Harmonoid 1.9k Aug 10, 2022
A project to showcase usage of basic principles to convert any 3D design into a working application using Flutter.

Developing apps with 3D designs in flutter This project is developed to showcase how we can use some basic principles to convert any 3D design into a

Manas Pratap Thakur 30 Dec 22, 2022
Amir Khan 47 Jan 8, 2023