iosflutterdartadmobgoogle-mobile-ads

Flutter google mobile ads only shows test ads on IOS


I have the following ad Repository

import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:my_app/data/api/constants.dart';

class AdMobRepository {
  late String liveBannerAdId;
  late String liveInterstitualAdId;
  late String liveRewardedAdId;

  AdMobRepository() {
    if (Platform.isAndroid) {
      liveBannerAdId = Constants.androidBannedAdId;
      liveInterstitualAdId = Constants.androidInterstitualAdId;
      liveRewardedAdId = Constants.androidRewardedAdId;
    } else if (Platform.isIOS) {
      liveBannerAdId = Constants.iosBannerAdId;
      liveInterstitualAdId = Constants.iosInterstitualAdId;
      liveRewardedAdId = Constants.iosRewardedAdId;
    } else {
      liveBannerAdId = "";
      liveInterstitualAdId = "";
      liveRewardedAdId = "";
    }
  }

  BannerAd getBannerAd({
    required AdSize size,
    void Function(Ad, LoadAdError)? onFailedLoad,
    void Function(Ad)? onLoad,
    void Function(Ad)? onAdOpened,
    void Function(Ad)? onAdImpression,
  }) {
    return BannerAd(
      adUnitId: kReleaseMode ? liveBannerAdId : BannerAd.testAdUnitId,
      request: AdRequest(),
      size: size,
      listener: BannerAdListener(
        onAdFailedToLoad: onFailedLoad ?? onFailedLoadFallback,
        onAdLoaded: onLoad,
        onAdImpression: onAdImpression,
        onAdOpened: onAdOpened,
      ),
    );
  }

  void onFailedLoadFallback(Ad ad, LoadAdError error) {
    ad.dispose();
  }

  void getInterstitualAd({required void Function(LoadAdError) onFailedLoad, void Function(InterstitialAd)? onLoad}) {
    InterstitialAd.load(
      adUnitId: kReleaseMode ? liveInterstitualAdId : InterstitialAd.testAdUnitId,
      request: AdRequest(),
      adLoadCallback: InterstitialAdLoadCallback(
        onAdLoaded: onLoad ?? onInterstitialAdLoadedFallback,
        onAdFailedToLoad: onFailedLoad,
      ),
    );
  }

  void onInterstitialAdLoadedFallback(InterstitialAd ad) {
    ad.fullScreenContentCallback = FullScreenContentCallback(
        onAdDismissedFullScreenContent: (ad) => ad.dispose(), onAdFailedToShowFullScreenContent: (ad, error) => ad.dispose());
  }

  void getRewardAd({required String userId, required void Function(LoadAdError) onFailedLoad, void Function(RewardedAd)? onLoad}) {
    RewardedAd.load(
      adUnitId: kReleaseMode ? liveRewardedAdId : RewardedAd.testAdUnitId,
      request: AdRequest(),
      rewardedAdLoadCallback: RewardedAdLoadCallback(
        onAdLoaded: onLoad ?? onRewardedAdLoadedFallback,
        onAdFailedToLoad: onFailedLoad,
      ),
      serverSideVerificationOptions: ServerSideVerificationOptions(userId: userId),
    );
  }

  void onRewardedAdLoadedFallback(RewardedAd ad) {
    ad.fullScreenContentCallback = FullScreenContentCallback(
        onAdDismissedFullScreenContent: (ad) => ad.dispose(), onAdFailedToShowFullScreenContent: (ad, error) => ad.dispose());
  }
}

And I have the following widget for banner ads

class MyBannerAd extends StatefulWidget {

  const MyBannerAd();

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

class _MyBannerAdState extends State<MyBannerAd> {
  late AdSize adSize;
  late AdMobRepository adRepository;
  late AnalyticsRepository analyticsRepository;
  bool adLoaded = false;
  BannerAd? anchoredBanner;

  @override
  void initState() {
    super.initState();
    adRepository = context.read<AdMobRepository>();
    analyticsRepository = context.read<AnalyticsRepository>();

    if (SizerUtil.deviceType != DeviceType.mobile && SizerUtil.orientation == Orientation.portrait) {
      adSize = AdSize.leaderboard;
    } else {
      adSize = AdSize.largeBanner;
    }

    final bannerAd = adRepository.getBannerAd(
      size: adSize,
      onFailedLoad: (ad, error) {
        print('banner ad failed to load: $error');
        ad.dispose();
      },
      onLoad: (ad) {
        setState(() {
          adLoaded = true;
          anchoredBanner = ad as BannerAd?;
        });
      },
      onAdImpression: (_) {
        analyticsRepository.sendBannerAdShownEvent();
      },
      onAdOpened: (_) {
        analyticsRepository.sendBannerAdClickEvent();
      },
    );

    bannerAd.load();
  }

  @override
  void dispose() {
    super.dispose();
    anchoredBanner?.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<SubscriptionBloc, SubscriptionState>(
      builder: (context, state) {
        final isLoaded = !adLoaded;

        if (isLoaded || state.hasSubscribed || anchoredBanner == null) return SizedBox.shrink();

        return Container(
          color: Colors.transparent,
          width: anchoredBanner!.size.width.toDouble(),
          height: anchoredBanner!.size.height.toDouble(),
          child: Center(
            child: Container(
              color: Colors.white,
              child: AdWidget(
                ad: anchoredBanner!,
              ),
            ),
          ),
        );
      },
    );
  }
}

But on IOS it is always showing test ads. How can this be when the app is built with flutter release mode with flutter build ios --release? The app is currently in review and I was thinking that these ads would stop being test ads whenever it is live on the app store.

But Apple sent us the following message

We noticed that your app or its screenshots include test advertisements. Apps or metadata items that include features that are for test or demonstration purposes are not appropriate for the App Store.

Next Steps

To resolve this issue, please revise your app to complete, remove, or fully configure any partially implemented features. Please ensure your screenshots do not include any images of demo, test, or other incomplete content

So how do I get rid of the test ads? Did I miss some XCode setting or?

I am using

flutter: 2.5.3
google_mobile_ads: ^0.13.4

And I also added the GADApplicationIdentifier to my info.plist

<key>GADApplicationIdentifier</key>
<string>{here I have the app Id}</string>

And I am testing on a real device with the testflight build

Side Note:

In admob setting I have added the following test IDFA

00000000-0000-0000-0000-000000000000

which seems to work for Test ads on all IOS devices.


Solution

  • Turns out I needed to remove the 00000000-0000-0000-0000-000000000000 from the test settings on admob. I no longer recieve test ads after that, but I do recieve ads in the release build now.