Search code examples
unity-game-engineadmobgoogleads-mobile-unity

google mobile ads lifecycle events don't activate in android build


I am currently working on game using the unity game engine. I am using google's mobile ads SDK to implement ads. According to the documentation, the ads have lifecycle events that can be utilized to customize the behavior of the ad.

For my purposes, I am using an interstitial ad. When I run the project in the editor, I can access these events and my code works the way it is supposed to work. However, when I make an android build, these ad lifecycle events don't fire off and I cannot get my ad to behave the way I want it to.

Here is my code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using GoogleMobileAds.Api;
using GoogleMobileAds.Common;
using System;
using UnityEngine.Events;

public class interstitialAd : MonoBehaviour
{

    public GameObject adFailedUI;
    public gameBehavior gamebehavior;

    public UnityEvent OnAdOpeningEvent;
    public UnityEvent OnAdClosedEvent;


    private InterstitialAd interstitial;
    private bool adLoaded = false;


    // Start is called before the first frame update
    void Start()
    {
        RequestInterstitial();
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    #region HELPER METHODS

    private AdRequest CreateAdRequest()
    {
        return new AdRequest.Builder().Build();
    }

    #endregion

    public void RequestInterstitial()
    {

        MonoBehaviour.print("Requesting Interstitial ad.");



        string adUnitId = "ca-app-pub-3940256099942544/1033173712";

        // Clean up interstitial before using it
        if (interstitial != null)
        {
            interstitial.Destroy();
            interstitial = null;
        }

        // Load an interstitial ad
        InterstitialAd.Load(adUnitId, CreateAdRequest(),
            (InterstitialAd ad, LoadAdError loadError) =>
            {
                if (loadError != null)
                {
                    MonoBehaviour.print("Interstitial ad failed to load with error: " +
                        loadError.GetMessage());
                    return;
                }
                else if (ad == null)
                {
                    MonoBehaviour.print("Interstitial ad failed to load.");
                    return;
                }

                MonoBehaviour.print("Interstitial ad loaded.");
                interstitial = ad;

                RegisterEventHandlers(interstitial);

               
            });
    }


    private void RegisterEventHandlers(InterstitialAd ad)
    {
        ad.OnAdFullScreenContentOpened += () =>
        {
            MonoBehaviour.print("Interstitial ad opening.");
            OnAdOpeningEvent.Invoke();
        };
        ad.OnAdFullScreenContentClosed += () =>
        {
            MonoBehaviour.print("Interstitial ad closed.");
            OnAdClosedEvent.Invoke();
            RequestInterstitial();
        };


        ad.OnAdImpressionRecorded += () =>
        {
            MonoBehaviour.print("Interstitial ad recorded an impression.");
        };
        ad.OnAdClicked += () =>
        {
            MonoBehaviour.print("Interstitial ad recorded a click.");
        };
        ad.OnAdFullScreenContentFailed += (AdError error) =>
        {
            RequestInterstitial();
            adFailedUI.SetActive(true);
            MonoBehaviour.print("Interstitial ad failed to show with error: " +
                        error.GetMessage());
        };
        ad.OnAdPaid += (AdValue adValue) =>
        {
            string msg = string.Format("{0} (currency: {1}, value: {2}",
                                       "Interstitial ad received a paid event.",
                                       adValue.CurrencyCode,
                                       adValue.Value);
            MonoBehaviour.print(msg);
        };
    }
    

    public void ShowAd()
    {
        if (this.interstitial.CanShowAd() && interstitial!=null)
        {
            this.interstitial.Show();
        }
        else
        {
            

        }
    }

    public void DestroyAd()
    {
        interstitial.Destroy();
    }

    

    public void OnDestroy()
    {
        DestroyAd();
    }
}

Please note that in the RequestInterstitial method, I have added my own debug messages in order to analyze what is happening. Of particular interest are the messages Requesting Interstitial ad. and Interstitial ad loaded. . The first prints when we enter attempt to load an ad and the other prints when the process is successful.

Whenever I run the project in my editor, I get the Interstitial ad loaded. log message, confirming that my ad was loaded. However, in my mobile build, I don't get this message. All I get is a requesting interstitial ad. It seems, in my mobile build, the code is unable to go beyond this point.

However, I can see my test ads in my mobile build. It's just that I cannot utilize any of the ad lifecycle events such as OnAdFullScreenContentClosed or OnAdFullScreenContentFailed .

I am using test ad units ID that is provided by google. I can see these test ads but cannot use them or interact with their events. What I am also unable to understand is that since the ad is clearly loaded (because I can see it), why don't my mobile logs show the Interstitial ad loaded message that they are supposed to?


Solution

  • After some search, I have found a solution.

    It turns out, the admob events run in a different thread. You can only control unity game objects inside the main unity thread. As such, even if the events fire off, they cannot do the thing that they are supposed to do since they are running in a different thread.

    My solution :

    Use a bool and change its value in the event. In the update method, check if the bool is true and if it is, run the method that you want to run.

    Since the update method runs on the main thread, there should be no problem.

    private bool adClosed = false;
    
    private bool adFailed = false;
    

    inside update method

    if (adClosed)
            {
                /*do whatever you want when ad closed*/
        
            }
    if (adFailed)
            {
                /*do whatever you want when ad fails to load*/
            }
    

    in the adclosed and adfailed events, set the value of these boolean variables.

    Also, reset the value of these variables back in false in the update method.