Firebase issues!

@dankly Yes I add a blank swift file with Firebase 10.2 :ok_hand:
Do you use firebase/admob.h or firebase/gma.h (Google Mobile Ads framework) ?

I used google mobile ads. Iā€™m not at my computer atm but Iā€™ll check what Iā€™ve done and get back to you. In the meantime, can you post your firebase::gma::initialize function block?

Thanks !

Projucer :

Extra Compiler Flags :
-fno-aligned-allocation

Extra Linker Flags :
$(OTHER_LDFLAGS) -ObjC -lsqlite3 -lz

Custom Plist :

<plist version="1.0">
    <dict>
        <key>NSAppTransportSecurity</key>
            <dict>
                <key>NSAllowsArbitraryLoads</key>
                    <true/>
            </dict>
    </dict>
</plist>

Extra System Frameworks :
CoreMotion, MediaPlayer, AdSupport, MessageUI, CoreServices, CoreTelephony, JavaScriptCore, Security, StoreKit, SystemConfiguration, UIKit, Foundation, CoreMedia, MetalKit

Framework Search Paths :
/X/Firebase/Firebase10/FirebaseAnalytics
/X/Firebase/Firebase10/FirebaseCrashlytics
/X/Firebase/Firebase10/Google-Mobile-Ads-SDK
/X/firebase_cpp_sdk10/xcframeworks

Extra Custom Frameworks :
/X/Firebase/firebase_cpp_sdk10/xcframeworks/firebase.xcframework
/X/Firebase/firebase_cpp_sdk10/xcframeworks/firebase_analytics.xcframework
/X/Firebase/firebase_cpp_sdk10/xcframeworks/firebase_gma.xcframework
/X/Firebase/Firebase10/FirebaseCrashlytics/FirebaseCrashlytics.xcframework
/X/Firebase/Firebase10/FirebaseCrashlytics/GoogleDataTransport.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FBLPromises.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FirebaseAnalytics.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FirebaseAnalyticsSwift.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FirebaseCore.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FirebaseCoreInternal.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/FirebaseInstallations.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/GoogleAppMeasurement.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/GoogleAppMeasurementIdentitySupport.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/GoogleUtilities.xcframework
/X/Firebase/Firebase10/FirebaseAnalytics/nanopb.xcframework
/X/Firebase/Firebase10/Google-Mobile-Ads-SDK/GoogleMobileAds.xcframework
/X/Firebase/Firebase10/Google-Mobile-Ads-SDK/UserMessagingPlatform.xcframework

Header Search Paths & Extra Library Search Paths (Debug & Release):
/X/Firebase/Firebase10/FirebaseAnalytics
/X/Firebase/Firebase10/FirebaseCrashlytics
/X/Firebase/Firebase10/Google-Mobile-Ads-SDK
/X/Firebase/firebase_cpp_sdk10/xcframeworks
/usr/lib/swift

Custom Xcode Flags (Debug & Release):
FRAMEWORK_SEARCH_PATHS=ā€œ/X/Firebase/Firebase10/FirebaseAnalytics /X/Firebase/Firebase10/FirebaseCrashlytics
/X/Firebase/Firebase10/Google-Mobile-Ads-SDK /X/Firebase/firebase_cpp_sdk10/xcframeworksā€, GCC_GENERATE_DEBUGGING_SYMBOLS=YES, STRIP_INSTALLED_PRODUCT=NO, COPY_PHASE_STRIP=NO

Xcode:

#include "firebase/analytics.h"
#include "firebase/analytics/event_names.h"
#include "firebase/analytics/parameter_names.h"
#include "firebase/analytics/user_property_names.h"
#include "firebase/app.h"
#include "firebase/future.h"
#include "firebase/gma.h"
#include "firebase/gma/ad_view.h"
#include "firebase/gma/interstitial_ad.h"
#include "firebase/gma/types.h"

using firebase::App;
using firebase::Future;
using firebase::gma::AdapterInitializationStatus;

ā€¦

    void initialise(const String& commandLine) override
    {
        printf("--- Initialisation Firebase\n");
        firebase::App* app = firebase::App::Create();
        printf("--- Created the firebase app %x\n",
                   static_cast<int>(reinterpret_cast<intptr_t>(app)));
        
        // Initialize the Google Mobile Ads library.
        printf("--- Initialisation GMA\n");
        firebase::InitResult result;
        Future<AdapterInitializationStatus> future = firebase::gma::Initialize(*app, &result);
        
        mainWindow.reset (new MainWindow (getApplicationName()));
        while (!ProcessEvents(1000)) {
            if (future.status() != firebase::kFutureStatusPending) {
                printf("\n\n==================YYYYYEEESSSSSS ==================\n\n\n");
                break;
            }
            else
                printf("WaitForFutureCompletion... kFutureStatusPending\n");
          }
     }

Do you drag & drop your ā€œGoogleService-info.plistā€ into Xcode (under App Name) ?
Or add this file into your Producer, File Explorer, Source ?

I add the plist to Projucer, alongside the source folder rather than in it, although im not sure that matters.

Have you setup an account in admob? Im not talking about firebase.google.com I mean admob.google.com

1 Like

Yes, my admob account is okay:

  • I have my Application ID (ca-app-pub-758873ā€¦)
  • Approval status Ready
  • Interstitiel ID okay (ca-app-pub-75887316399ā€¦)
  • Payments ready

My GoogleService-Info.plist file:
(Download from Firebase.google.com after link admob with firebase. I just changed bool IS_ADS_ENABLED and IS_ANALYTICS_ENABLED to YES)
Is there anything else to do?

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CLIENT_ID</key>
	<string>4882X07sls.apps.googleusercontent.com</string>
	<key>REVERSED_CLIENT_ID</key>
	<string>com.googleusercontent.apps.X</string>
	<key>API_KEY</key>
	<string>AIzaSyB4wAEIkpxleMX</string>
	<key>GCM_SENDER_ID</key>
	<string>488244303159</string>
	<key>PLIST_VERSION</key>
	<string>1</string>
	<key>BUNDLE_ID</key>
	<string>com.X</string>
	<key>PROJECT_ID</key>
	<string>X-firebase</string>
	<key>STORAGE_BUCKET</key>
	<string>X-firebase.appspot.com</string>
	<key>IS_ADS_ENABLED</key>
	<true></true>
	<key>IS_ANALYTICS_ENABLED</key>
	<true></true>
	<key>IS_APPINVITE_ENABLED</key>
	<true></true>
	<key>IS_GCM_ENABLED</key>
	<true></true>
	<key>IS_SIGNIN_ENABLED</key>
	<true></true>
	<key>GOOGLE_APP_ID</key>
	<string>1:488244303X</string>
	<key>ADMOB_APP_ID</key>
	<string>ca-app-pub-7588731X</string>
</dict>
</plist>

I added my app ID to the custom plist in projucer

GADApplicationIdentifier
ca-app-pub-7922487446890273~YOURID

See if that does anything for you

Iā€™m trying to do this on my phone and itā€™s deleted the key and string but you understand what I mean donā€™t you?

I think this will add the ID to the info.plist in your project rather than it being in the google services one

Yes I add this GADApplicationIdentifier in Projucer Custom Plist but it doesnā€™t work betterā€¦
Like this :

<plist version="1.0">
    <dict>
        <key>NSAppTransportSecurity</key>
            <dict>
                <key>NSAllowsArbitraryLoads</key>
                    <true/>
            </dict>
        <key>GADApplicationIdentifier</key>
        <string>ca-app-pub-7588731639915518~X</string>
    </dict>
</plist>

Thanks

Right. Another observation, some of my includes are different to yours and I donā€™t have any ā€˜usingā€™ at all.

Tomorrow when I get a chance Iā€™ll upload a bare bones version of my main.cpp and maincomponent.h and maincomponent.cpp to see if you can edit and use it with your projucer file, just to get the demo adds working. If that works, itā€™s a problem in your source files, if not it should be a projucer issue.

1 Like

Yes!!! Perfect! Thanks !

This thread is great, and @dankly that would be really awesome. Thank you and everyone sharing their experiences here :slight_smile:

1 Like

Main.cpp

#include <JuceHeader.h>
#include ā€œMainComponent.hā€
#include ā€œfirebase/app.hā€
#include ā€œfirebase/gma.hā€

//==============================================================================
class AdsDemoApplication : public juce::JUCEApplication
{
public:
//==============================================================================
AdsDemoApplication() {}

const juce::String getApplicationName() override       { return ProjectInfo::projectName; }
const juce::String getApplicationVersion() override    { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override             { return true; }

//==============================================================================
void initialise (const juce::String& commandLine) override
{
    // Initialize the Google Mobile Ads library.
    
    firebase::InitResult result;
    firebase::Future<firebase::gma::AdapterInitializationStatus> future =
      firebase::gma::Initialize(&result);

    if (result != firebase::kInitResultSuccess) {
      // Initialization immediately failed, most likely due to a missing dependency.
      // Check the device logs for more information.
      return;
    }

    // Monitor the status of the future.
    // See "Use a Future to monitor the completion status of a method call" below.
    if (future.status() == firebase::kFutureStatusComplete &&
        future.error() == firebase::gma::kAdErrorCodeNone) {
      // Initialization completed.
    } else {
      // Initialization on-going, or an error has occurred.
    }
    
    mainWindow.reset (new MainWindow (getApplicationName()));
}

void shutdown() override
{
    mainWindow = nullptr; // (deletes our window)
}

//==============================================================================
void systemRequestedQuit() override
{
    quit();
}

void anotherInstanceStarted (const juce::String& commandLine) override {}

//==============================================================================

class MainWindow    : public juce::DocumentWindow
{
public:
    MainWindow (juce::String name)
        : DocumentWindow (name,
                          juce::Desktop::getInstance().getDefaultLookAndFeel()
                                                      .findColour (juce::ResizableWindow::backgroundColourId),
                          DocumentWindow::allButtons)
    {
        setUsingNativeTitleBar (true);
        setContentOwned (new MainComponent(), true);

       #if JUCE_IOS || JUCE_ANDROID
        setFullScreen (true);
       #else
        setResizable (true, true);
        centreWithSize (getWidth(), getHeight());
       #endif

        setVisible (true);
    }

    void closeButtonPressed() override
    {
        JUCEApplication::getInstance()->systemRequestedQuit();
    }

private:
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};

private:
std::unique_ptr mainWindow;
};

//==============================================================================

START_JUCE_APPLICATION (AdsDemoApplication)

MainComponent.h

#pragma once

#include <JuceHeader.h>
#include ā€œfirebase/future.hā€
#include ā€œfirebase/gma/ad_view.hā€
#include ā€œfirebase/gma/interstitial_ad.hā€

//==============================================================================

class MainComponent : public juce::Component,
private juce::MultiTimer
{
public:
//==============================================================================
MainComponent();
~MainComponent() override;

//==============================================================================

void paint (juce::Graphics&) override;
void resized() override;
void timerCallback (int) override;

private:

// Banner ad requisites

std::unique_ptr<firebase::gma::AdView> adView;

juce::StringRef googleBannerID = "ca-app-pub-3940256099942544/2934735716"; // Demo

//==============================================================================

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)

};

MainComponent.cpp

#include ā€œMainComponent.hā€
#include ā€œfirebase/admob/types.hā€

//==============================================================================
MainComponent::MainComponent()
{
auto area = juce::desktop::getInstance().getDisplays().getMainDisplay().userArea;
setSize(area.getWidth(), area.getHeight());

startTimer(1, 1000); // Banner Ad

setSize (620, 300);

}

MainComponent::~MainComponent()
{
if( adView.get() ) {adView->Destroy();}
}

void MainComponent::timerCallback(int timerID)
{
// Banner Ad Timer

if (timerID == 1)
{
    stopTimer(1);
    
    adView = std::make_unique<firebase::gma::AdView>();
    auto adSize = firebase::gma::AdSize::kBanner;
    
    adView->Initialize(static_cast<firebase::gma::AdParent>(getTopLevelComponent()->getWindowHandle()),
                           googleBannerID,
                       adSize);
    
    adView->SetPosition(firebase::gma::AdView::kPositionTop);
    
    firebase::gma::AdRequest ad_request;
    firebase::Future<firebase::gma::AdResult> load_ad_result = adView->LoadAd(ad_request);
    
    firebase::Future<void> result = adView->Show();
}

}

void MainComponent::paint (juce::Graphics& g) {g.fillAll(juce::Colours::black);}

void MainComponent::resized() {}

End Result

2 Likes

BIG BIG Thanks @dankly !!!

Yes, I have the same Result with the Banner Ad !

Butā€¦
If I have a error if check it like this :
if (adView->LoadAdLastResult().error() == firebase::gma::kAdErrorCodeNone)

I donā€™t know if itā€™s important. Is it the same with your app?

Your Banner Ad work on App Store ?

And I canā€™t get the code to work with Interstitial Ad, nothing is displayedā€¦
My Maincomponent.cpp:

#include "MainComponent.h"

//==============================================================================
MainComponent::MainComponent()
{
    //auto area = juce::Desktop::getInstance().getDisplays().getMainDisplay().userArea;
    auto area = juce::Desktop::getInstance().getDisplays().getMainDisplay().userArea;
    setSize(area.getWidth(), area.getHeight());
    startTimer(1, 1000); // Banner Ad

    setSize (620, 300);
}

MainComponent::~MainComponent()
{
    if( adView.get() ) {adView->Destroy();}
    if( interstitial_ad.get() ) {interstitial_ad = nullptr;}
}

void MainComponent::timerCallback(int timerID)
{
// Banner Ad Timer

    if (timerID == 1)
    {
        stopTimer(1);
        
        // Configure test device ids before loading ads.
        //
        // This example uses ad units that are specially configured to return test ads
        // for every request. When using your own ad unit IDs, however, it's important
        // to register the device IDs associated with any devices that will be used to
        // test the app. This ensures that regardless of the ad unit ID, those
        // devices will always receive test ads in compliance with AdMob policy.
        //
        // Device IDs can be obtained by checking the logcat or the Xcode log while
        // debugging. They appear as a long string of hex characters.
        const std::vector<std::string> kTestDeviceIDs = {
            "2077ef9a63d2b398840261c8221a0c9b", "098fe087d987c9a878965454a65654d7", "F8BB1C28-BAE8-11D6-9C31-00039315CD46"};
        
        // Do once after Google Mobile Ads C++ SDK initialization.
        // These settings will affect all Ad Load operations.
        firebase::gma::RequestConfiguration request_configuration;
        request_configuration.test_device_ids = kTestDeviceIDs;
        firebase::gma::SetRequestConfiguration(request_configuration);


        // InterstitialAd
        // Load and Display a Interstitial Ad
        //
        firebase::gma::AdRequest ad_request;
        
#if JUCE_ANDROID
        static const std::vector<std::string> kKeywords({"GMA", "C++", "Fun"});
        static const char *kAdNetworkExtrasClassName = "com/google/ads/mediation/admob/AdMobAdapter";
#elif JUCE_IOS
        static const std::vector<std::string> kKeywords({"GMA", "C++", "Fun"});
        static const char *kAdNetworkExtrasClassName = "GADExtras";
#endif

        // Configure additional keywords to be used in targeting.
        for (auto keyword_iter = kKeywords.begin(); keyword_iter != kKeywords.end();
             ++keyword_iter) {
          ad_request.add_keyword((*keyword_iter).c_str());
        }

        // "Extra" key value pairs can be added to the request as well. Typically
        // these are used when testing new features.
        ad_request.add_extra(kAdNetworkExtrasClassName, "the_name_of_an_extra", "the_value_for_that_extra");
        
        // Load And Show InterstitialAd
        LoadAndShowInterstitialAd(ad_request);
        // Or Load And Show Banner
        //LoadAndShowBanner(ad_request);
    }
}

void MainComponent::paint (juce::Graphics& g) {
    g.fillAll(juce::Colours::blueviolet);
}


void MainComponent::LoadAndShowBanner(const firebase::gma::AdRequest &ad_request) {
    printf("===\nGMA : Configurer un banner\n");
    adView = std::make_unique<firebase::gma::AdView>();
    auto adSize = firebase::gma::AdSize::kBanner;
     
    adView->Initialize(static_cast<firebase::gma::AdParent>(getTopLevelComponent()->getWindowHandle()), googleBannerID, adSize);
     
    adView->SetPosition(firebase::gma::AdView::kPositionBottom);
     
    //firebase::gma::AdRequest ad_request;
    firebase::Future<firebase::gma::AdResult> load_ad_result = adView->LoadAd(ad_request);
    
    // Check for errors.
    if (adView->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) {
      // Log information as to why the loadAd request failed.
        printf("OK\n");
        const firebase::gma::AdResult *result_ptr = adView->LoadAdLastResult().result();
        if (result_ptr != nullptr) {
            printf(
                "Banner::loadAd Failure - Code: %d Message: %s Domain: %s\n",
                result_ptr->ad_error().code(),
                result_ptr->ad_error().message().c_str(),
                result_ptr->ad_error().domain().c_str());
        }
    }
    else {
        printf("Banner Load ERROR\n");
    }
    firebase::Future<void> result = adView->Show();
}

void MainComponent::LoadAndShowInterstitialAd(const firebase::gma::AdRequest &ad_request) {
    printf("===\nGMA : Configurer un InterstitialAd\n");
    
    printf("\nLoad and show an interstitial ad:\n");
    // Initialize an InterstitialAd.
    interstitial_ad = std::make_unique<firebase::gma::InterstitialAd>();
    
    interstitial_ad->Initialize(static_cast<firebase::gma::AdParent>(getTopLevelComponent()->getWindowHandle()));

    // Block until the interstitial ad completes initialization.
    //WaitForFutureCompletion(interstitial_ad->InitializeLastResult());
    interstitial_ad->InitializeLastResult();

    // Check for errors.
    if (interstitial_ad->InitializeLastResult().error() != firebase::gma::kAdErrorCodeNone) {
        printf("\nInterstitial_ad Initialize Error\n");
        interstitial_ad = nullptr;
    }
    
    // Setup the interstitial ad's listeners.
    LoggingFullScreenContentListener fullscreen_content_listener;
    interstitial_ad->SetFullScreenContentListener(&fullscreen_content_listener);
    firebase::gma::PaidEventListener paid_event_listener;
    interstitial_ad->SetPaidEventListener(&paid_event_listener);
    
    // Load an ad.
    interstitial_ad->LoadAd(googleInterstitialID, ad_request);
    
    //WaitForFutureCompletion(interstitial_ad->LoadAdLastResult());
    interstitial_ad->LoadAdLastResult();
    
    // Check for errors.
    if (interstitial_ad->LoadAdLastResult().error() != firebase::gma::kAdErrorCodeNone) {
      // Log information as to why the loadAd request failed.
        printf("Load OK\n");
          const firebase::gma::AdResult *result_ptr =
              interstitial_ad->LoadAdLastResult().result();
          if (result_ptr != nullptr) {
              printf(
                "InterstitialAd::load Ad Failure - Code: %d Message: %s Domain: %s\n",
                result_ptr->ad_error().code(),
                result_ptr->ad_error().message().c_str(),
                result_ptr->ad_error().domain().c_str());
          }
    }
    else {
        printf("interstitial_ad Load ERROR\n");
    }
        
    // Show the ad.
    printf("Showing the interstitial ad.\n");
    firebase::Future<void> result = interstitial_ad->Show();
    interstitial_ad->ShowLastResult();
    
    // Check for errors.
    if (interstitial_ad->ShowLastResult().error() != firebase::gma::kAdErrorCodeNone) {
      // Log information as to why the loadAd request failed.
        printf("Show OK\n");
        const firebase::gma::AdResult *resultShow_ptr = interstitial_ad->LoadAdLastResult().result();
        if (resultShow_ptr != nullptr) {
            printf("InterstitialAd::Show Ad Failure - Code: %d Message: %s Domain: %s\n",
                     resultShow_ptr->ad_error().code(),
                     resultShow_ptr->ad_error().message().c_str(),
                     resultShow_ptr->ad_error().domain().c_str());
          }
    }
    else {
        printf("interstitial_ad Show ERROR\n");
    }
}

void MainComponent::resized() {}

Hey @tobyscreamer!
I have the same issue and it makes me a headache with interstitial ad.
(Admob is working with banner ad, but the intertitial ad isnt showing up, even if the initialization is succesfull)
Is there a chance you could solve this problem somehow?

Hello @szaan !

I understand your frustration with the interstitial ad issue. Itā€™s important to note that interstitial ads require a slightly different approach compared to banner (Itā€™s more slow). To ensure smooth delivery and display of interstitial ads, itā€™s recommended to preload them well in advance before requesting their display. Personally, I make sure to always have an interstitial ad preloaded in the background.

While Iā€™m not a C++ specialist (sorryā€¦), thatā€™s my ā€œadmob.cppā€ and ā€œadmob.hā€ (it works on iOS and Android) :
admob.cpp :


//==============================================================================
InterstitialAd::InterstitialAd(StringRef adID, Component& owner)
{
    owner.addAndMakeVisible(this);
    interstitialID = adID;
}

InterstitialAd::~InterstitialAd()
{
}

#if JUCE_IOS || JUCE_ANDROID
void InterstitialAd::timerCallback()
{
    stopTimer();
}

void InterstitialAd::loadAd()
{
    if(onLoad)
        return;
    onLoad = true;
    interstitialView.reset(new firebase::gma::InterstitialAd());
            
    callbacks.errorCallback = [this](const firebase::Future<void>& result) {
        DBG( "callbacks errorCallback error!\n");
    };
            
    callbacks.initCallback = [this](const firebase::Future<void>& result) {
        DBG("callbacks initCallback\n");
        interstitialView->SetFullScreenContentListener(this);
        
        // Then, more information must be provided via an AdRequest when
        // loading individual ads.
        firebase::gma::AdRequest ad_request;

        // "Extra" key value pairs.
        ad_request.add_keyword("GMA");
        ad_request.add_keyword("C++");
        ad_request.add_keyword("Fun");
                
        // Mediation Adapter Extras.
#if JUCE_ANDROID
        const char* ad_network_extras_class_name = "com/google/ads/mediation/admob/AdMobAdapter";
#elif JUCE_IOS
        const char* ad_network_extras_class_name = "GADExtras";
#endif

        ad_request.add_extra(ad_network_extras_class_name, "extra_name", "extra_value");
                
        // These settings will affect all Ad Load operations.
        firebase::gma::RequestConfiguration configuration;
        configuration.max_ad_content_rating = firebase::gma::RequestConfiguration::kMaxAdContentRatingPG;
        configuration.tag_for_child_directed_treatment = firebase::gma::RequestConfiguration::kChildDirectedTreatmentTrue;
        configuration.tag_for_under_age_of_consent = firebase::gma::RequestConfiguration::kUnderAgeOfConsentFalse;
        configuration.test_device_ids.push_back("XXXXXXXX");
        configuration.test_device_ids.push_back("XXXXXXXX");
        configuration.test_device_ids.push_back("XXXXXXXX");
        configuration.test_device_ids.push_back("XXXXXXXX");
        configuration.test_device_ids.push_back("XXXXXXXX"); // etc....
        firebase::gma::SetRequestConfiguration(configuration);
                
        interstitialView->LoadAd(interstitialID, ad_request);
        interstitialView->LoadAdLastResult();
        onLoad = false;
    };
            
    DBG("======= Initialize interstitialView =========\n");
#if JUCE_ANDROID
    interstitialView->Initialize(static_cast<firebase::gma::AdParent>(getMainActivity()));
#elif JUCE_IOS
    interstitialView->Initialize(static_cast<firebase::gma::AdParent>(getWindowHandle()));
#endif
    interstitialView->InitializeLastResult().OnCompletion(InterstitialAdCallbacks::InitCallback, &callbacks);
}

bool InterstitialAd::checkAd()
{
    if (isTimerRunning()) // If the timer is running it can mean that the last ad is less than a minute old, so no ad.
        return false;
    else if(auto* ad = interstitialView.get()) {
        if(ad->InitializeLastResult().status() == 0 &&
           ad->InitializeLastResult().error () == 0 &&
           ad->LoadAdLastResult()    .status() == 0 &&
           ad->LoadAdLastResult()    .error () == 0) {
            return true;
        }
        else {
            DBG("Ad check NOK\n");
            return false;
        }
    }
    else {
        DBG("Ad check NOK\n");
        return false;
    }
}

bool InterstitialAd::showAd()
{
    if(onLoad || *onAd)
        return false;
    
    if(auto* ad = interstitialView.get())
    {
        if(checkAd()) {
#if JUCE_IOS || JUCE_ANDROID
            crashlytics::LogEvent("InterstitialAd", "showAd", "Okay");
#endif
            //show it
            if (playButton->getToggleState()) onPlay = true;
            else onPlay = false; // do play after ads
            ad->Show();
            return true;
        }
        else {
#if JUCE_IOS || JUCE_ANDROID
            crashlytics::LogEvent("InterstitialAd", "showAd", "Failed");
#endif
            // Ad failed, we want to try again, for later...
            DBG("Ad failed\n");
            if(!isTimerRunning() && !tryAgainLoadAd) {
                tryAgainLoadAd = true;
                
                loadAd();
                Timer::callAfterDelay (5000,  [this] {
                    tryAgainLoadAd = false;
                });
            }
            *onAd = false;
            return false;
        }
    }
    else {
        *onAd = false;
        return false;
    }
}

void InterstitialAd::OnAdClicked() {
    DBG("Ad Clicked\n");
#if JUCE_IOS || JUCE_ANDROID
    crashlytics::LogEvent("InterstitialAd", "OnAdClicked", "Ad Clicked");
#endif
    // We want a new Ads for later.
    *onAd = false;
    Timer::callAfterDelay (10000,  [this] {
        loadAd();
    });
}
void InterstitialAd::OnAdDismissedFullScreenContent() {
    DBG("Ad Dismissed by user\n");
#if JUCE_IOS || JUCE_ANDROID
    crashlytics::LogEvent("InterstitialAd", "OnAdDismissedFullScreenContent", "Ad Dismissed by user");
#endif
    *onAd = false;
    if (onPlay && !playButton->getToggleState()) // Si on est en pause, on fait play car pub finit
        playButton->setToggleState(true,sendNotification);
    // We want a new Ads for later.
    Timer::callAfterDelay (10000,  [this] {
        loadAd();
    });
}
void InterstitialAd::OnAdFailedToShowFullScreenContent(const firebase::gma::AdError& error) {
    *onAd = false;
#if JUCE_IOS || JUCE_ANDROID
    crashlytics::LogEvent("InterstitialAd", "OnAdFailedToShowFullScreenContent", error.message().c_str());
#endif
    printf("Ad Failed To Show %s\n", error.message().c_str());
    // Ad failed, we want to try again, for later...
    Timer::callAfterDelay (10000,  [this] {
        loadAd();
    });
}
void InterstitialAd::OnAdImpression() {
    DBG( "Ad Impression\n");
#if JUCE_IOS || JUCE_ANDROID
    crashlytics::LogEvent("InterstitialAd", "OnAdImpression", "Ad Impression");
#endif
    *onAd = true;
}
void InterstitialAd::OnAdShowedFullScreenContent() {
#if JUCE_IOS || JUCE_ANDROID
    crashlytics::LogEvent("InterstitialAd", "OnAdShowedFullScreenContent", "0");
#endif
    *onAd = true;
    if (playButton->getToggleState()) // Si on est en play, on fait pause pendant la pub
        playButton->setToggleState(false,sendNotification);
    
    startTimer(INTERVAL_AD * 1000);
}
#endif

admob.h :

#include "../JuceLibraryCode/JuceHeader.h"
#if JUCE_IOS || JUCE_ANDROID
#include "firebase/future.h"
#include "firebase/gma.h"
#include "firebase/gma/interstitial_ad.h"
#include "firebase/analytics.h"
namespace crashlytics = ::firebase::analytics;
#endif
#include "Parameters.h"

#define STATIC_CALLBACK_DECL(name) \
static void name##Callback(const firebase::Future<void>& result, void* userData);

#define FUNC_CALLBACK_DECL(name) \
std::function<void(const firebase::Future<void>&)> name##Callback

//==============================================================================
struct InterstitialAdCallbacks
{
#if JUCE_IOS || JUCE_ANDROID
    STATIC_CALLBACK_DECL(Init);
    STATIC_CALLBACK_DECL(Load);
    STATIC_CALLBACK_DECL(Show);

    FUNC_CALLBACK_DECL(init);
    FUNC_CALLBACK_DECL(load);
    FUNC_CALLBACK_DECL(show);
    FUNC_CALLBACK_DECL(error);
#endif
};

struct InterstitialAd :
    public Component,
    public Timer
#if JUCE_IOS || JUCE_ANDROID
   ,public firebase::gma::FullScreenContentListener
#endif
{
    InterstitialAd(StringRef adID, Component& owner);
    ~InterstitialAd();
#if JUCE_IOS || JUCE_ANDROID
    void OnAdClicked() override;
    void OnAdDismissedFullScreenContent() override;
    void OnAdFailedToShowFullScreenContent(const firebase::gma::AdError& error) override;
    void OnAdImpression() override;
    void OnAdShowedFullScreenContent() override;
    
    void loadAd();
    bool checkAd();
    bool showAd();

    InterstitialAdCallbacks callbacks;
    ImageButton* playButton = nullptr; // To play after an ad and pause before
    bool *onAd              = nullptr; // To find out if we are broadcasting Ads
    bool tryAgainLoadAd     = false;   // To retest to load an ad when no Networks for example
    bool onPlay             = false;   // To make a play after the ad
    bool onLoad             = false;   // For is loading a new ad
    
private:
    void timerCallback() override;
    
    std::unique_ptr<firebase::gma::InterstitialAd> interstitialView;
#endif
    StringRef interstitialAdUnitID;
    StringRef interstitialID;
};
#undef STATIC_CALLBACK_DECL
#undef FUNC_CALLBACK_DECL

@tobyscreamer Thank you soo much the fast answer, and sorry for late response.
I could solve my issue later, and it was like I wanted to show my ad, before it is loaded correctly.
So I just had to wait until it loads and just after show in on the screen.

Can I ask, if you implemented push notification with firebase too?

Sorry, but no, I havenā€™t implemented Firebaseā€™s push notifications.

I got push notification working successfully on iOS using latest Firebase SDK!

There are few extra Swift related flags I had to set. Iā€™ve updated instructions on sample project here

1 Like