nooralibutt / easy-ads

This repo has the integration of AdMob, AppLovin-Max, UnityAds, and Facebook ads.
https://pub.dev/packages/easy_ads_flutter
BSD 3-Clause "New" or "Revised" License
38 stars 19 forks source link

First Interstitial ad fails - Invalid destroy ads #25

Closed nooralibutt closed 2 years ago

nooralibutt commented 2 years ago

Hi again, I found a bug and did a minor fix for unity Interstitial ads. Did a merge request to your project with it.

I’m having some trouble getting the first Interstitial ad to work. The second and following taps are working, but the first tap I get there is no Interstitial ad loaded…

What I do is I initialize EasyAd in main.dart:

await EasyAds.instance.initialize(
    adIdManager,
    testMode: true,
    adMobAdRequest: const AdRequest(),
    admobConfiguration:
        RequestConfiguration(testDeviceIds: ['adakjhdjkahdahkjdahkdhk']),
  );

Later on in another screen I load the interstitialad in the initState like this:

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

    if (!EasyAds.instance.isInterstitialAdLoaded())
      EasyAds.instance.loadInterstitialAd();

  }

OnTap I cal this method but EasyAds.instance.isInterstitialAdLoaded() is always returning false. I am probably missing something… I can see the ad is loaded in the debuglog: D/AppLovinSdk( 8723): [MaxInterstitialAd] isReady() true for ad unit id 6050eeaf2220d59d

HandleMatchTap(MaterialPageRoute push, BuildContext context) {
    if (EasyAds.instance.isInterstitialAdLoaded() && !interstitialAdShowed) {
      if (EasyAds.instance.showInterstitialAd()) {
        // Canceling the last callback subscribed
        _streamSubscription?.cancel();
        // Listening to the callback from showInterstitialAd()
        _streamSubscription = EasyAds.instance.onEvent.listen((event) {
          if (event.adUnitType == AdUnitType.interstitial &&
              event.type == AdEventType.adDismissed) {
            Navigator.push(context, push);
          } else if (event.adUnitType == AdUnitType.interstitial &&
              event.type == AdEventType.adShowed) {
            if (this.mounted) {
              setState(() {
                interstitialAdShowed = true;
              });
            }
          } else if (event.adUnitType == AdUnitType.interstitial &&
              (event.type == AdEventType.adFailedToLoad ||
                  event.type == AdEventType.adFailedToShow)) {
            Navigator.push(context, push);
          }
        });
      }
    } else {
      Navigator.push(context, push);
    }
  }
nooralibutt commented 2 years ago
@override
  void initState() {
    super.initState();
    loadData(true);

      EasyAds.instance.loadInterstitialAd();
  }

You are checking EasyAds.instance.isInterstitialAdLoaded and then loading it again. You don’t need to check first. If any ad has been loaded already and you call load again. It won’t reload so don’t worry about that.

In the next code, you are again checking if the ad is loaded or not and checking if it's not being displayed already, you don’t need to do that either. showed actually returns a boolean value indicating it is displayed or not. So your whole code would become like this:

HandleMatchTap(MaterialPageRoute push, BuildContext context) {
     if (EasyAds.instance.showInterstitialAd()) {
          interstitialAdShowed = true;
       _streamSubscription?.cancel();
       _streamSubscription = EasyAds.instance.onEvent.listen((event) {
         if (event.adUnitType == AdUnitType.interstitial &&
             event.type == AdEventType.adDismissed) {
           _streamSubscription?.cancel();
           Navigator.push(context, push);
         } 
       });
     }
   } else {
     Navigator.push(context, push);
   }
 }

You don't need to override failed to load, cz if ad wasn't loaded it would not go into if block.

pikkenix commented 2 years ago

Thank you for your clarification. When should I use the isInterstitialAdLoaded?

in the example in the repo you Initialize in the main screen, in the next screen (list-screen) you show the interstitial or rewarded ad. In the following screen (details screen) you load an interstitial but it is never showed. Why is the example like this, why are you loading a new ad after showing the ad and not loading it in the initstate in the screens where you intendent to show an ad?

nooralibutt commented 2 years ago

As you can see, it is a shared instance. It is not bounded to any screen.

You can load anywhere and show anywhere in the screen. I have loaded the ads by default. You don’t even need to load it manually

pikkenix commented 2 years ago

Edited as you recommended but now I no ads is displayed. If I watch EasyAds.instance.isInterstitialAdLoaded() while debuging I see it is always false when I call HandleMatchTap(MaterialPageRoute push, BuildContext context)...

nooralibutt commented 2 years ago

You can check logs. And see if events are there ad loaded

On Thu, 21 Oct 2021 at 11:21 PM, Daniel Eriksson @.***> wrote:

Edited as you recommended but now I no ads is displayed. If I watch EasyAds.instance.isInterstitialAdLoaded() while debuging I see it is always false when I call HandleMatchTap(MaterialPageRoute push, BuildContext context)...

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nooralibutt/easy-ads/issues/25#issuecomment-948887235, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSNCKXW2JAIMH7HXPKSQZLUIBK3DANCNFSM5GMPB66A .

-- Regards Noor Ali Butt

pikkenix commented 2 years ago

Found the problem. If I'm having two screens - both running the following code:

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

EasyAds.instance.loadInterstitialAd();

}

@override dispose() { EasyAds.instance.disposeAds(); super.dispose(); }

The dispose() will run after the initstate. This means all the ads will first be loaded when running intistate, and then all ads is disposed after loading... Sounds stupid to skip the disposeAds() as the list of ads loaded will grow and grow... So should I insted run the EasyAds.instance.disposeAds(); after the ad is shown?

nooralibutt commented 2 years ago

You should never call dispose ads. Dispose ads should be called when you terminate the app. I think I should remove the dispose ads function

pikkenix commented 2 years ago

Ok, the example uses the disposeads. I remove all my disposeads then. Thanks for great support!

nooralibutt commented 2 years ago

I will release the new version and clearly mention on dispose ads that you should not call it until unless you completely want to remove ads altogether

On Fri, 22 Oct 2021 at 11:12 AM, Daniel Eriksson @.***> wrote:

Ok, the example uses the disposeads. Remove all my disposeads then. Thanks for great support!

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/nooralibutt/easy-ads/issues/25#issuecomment-949316405, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSNCKRHNVEHSTTZOZZZRVDUID6D5ANCNFSM5GMPB66A .

-- Regards Noor Ali Butt

nooralibutt commented 2 years ago

@pikkenix released the latest version, updated docs as well. I will be closing this ticket now.