Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullReferenceException in ListenToAdEvents() #3719

Open
oskari-leppaaho opened this issue Jan 17, 2025 · 1 comment
Open

NullReferenceException in ListenToAdEvents() #3719

oskari-leppaaho opened this issue Jan 17, 2025 · 1 comment
Assignees
Labels
Support General question, Installation question, or feedback.

Comments

@oskari-leppaaho
Copy link

[REQUIRED] Step 1: Describe your environment

  • Unity version: 2022.3.30f1
  • Google Mobile Ads Unity plugin version: 8.6.0
  • Plugin installation method: .unitypackage import (Unity package manager, .unitypackage import)
  • Platform: Android (iOS, Android, Unity Editor)
  • Platform OS version: Android 14 (eg iOS 10, Android 9)
  • Any specific devices issue occurs on: samsung SM-S918B
  • Mediation ad networks used, and their versions: AdMob? not sure where to check

[REQUIRED] Step 2: Describe the problem

An interstitial ad doesn't show and after that also banner ads stop appearing

Steps to reproduce:

Relevant pieces from our logs:

14:11:32 Log: Social authenticate success for GooglePlay
14:11:34 Log: Creating banner view
14:11:34 Log: Loading banner ad.
14:11:35 Log: Destroying banner view.
14:11:36 Exception: NullReferenceException: Object reference not set to an instance of an object.
BannerAdWrapper.<ListenToAdEvents>b__12_0 () (at <00000000000000000000000000000000>:0)
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <00000000000000000000000000000000>:0)
UnityEngine.AndroidJavaProxy.Invoke (System.String methodName, System.Object[] args) (at <00000000000000000000000000000000>:0)
UnityEngine.AndroidJavaProxy.Invoke (System.String methodName, System.IntPtr javaArgs) (at <00000000000000000000000000000000>:0)
UnityEngine._AndroidJNIHelper.InvokeJavaProxyMethod (UnityEngine.AndroidJavaProxy proxy, System.IntPtr jmethodName, System.IntPtr jargs) (at <00000000000000000000000000000000>:0)
Rethrow as TargetInvocationException: GoogleMobileAds.Android.BannerClient.onAdLoaded()
UnityEngine.AndroidJavaProxy.Invoke (System.String methodName, System.Object[] args) (at <00000000000000000000000000000000>:0)
UnityEngine.AndroidJavaProxy.Invoke (System.String methodName, System.IntPtr javaArgs) (at <00000000000000000000000000000000>:0)
UnityEngine._AndroidJNIHelper.InvokeJavaProxyMethod (UnityEngine.AndroidJavaProxy proxy, System.IntPtr jmethodName, System.IntPtr jargs) (at <00000000000000000000000000000000>:0)

Relevant Code:

It seems to me that our code pretty much follows the examples in your documentation

My guess is that it's the _bannerView in ListenToAdEvents() that is null in the exception.

BannerAdWrapper.cs:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds;
using GoogleMobileAds.Api;
using AdSize = GoogleMobileAds.Api.AdSize;

public class BannerAdWrapper
{
    // These ad units are configured to always serve test ads.
#if UNITY_ANDROID
    // omitted to not share private information
    private string _adUnitId = "XXX";
#elif UNITY_IPHONE
    // omitted to not share private information
  private string _adUnitId = "XXX";
#else
  private string _adUnitId = "unused";
#endif


    private int bannerSizeToPixels(int size)
    {
        return size * Mathf.RoundToInt(Screen.dpi / 160);
    }

    private int pixelsToBannerSize(int size)
    {
        return size / Mathf.RoundToInt(Screen.dpi / 160);
    }

    /// <summary>
    /// Creates a 320x50 banner view at `pos` of the screen.
    /// </summary>
    private void CreateBannerView(AdPosition pos)
    {
        Debug.Log("Creating banner view");

        // If we already have a banner, destroy the old one.
        if (_bannerView != null)
        {
            DestroyAd();
        }

        int bannerWidth = 320;
        int bannerHeight = 100; //Because AdSize.Banner measures 320x50
        Debug.Log("Screen.width = " + Screen.width + "; Screen.height = " + Screen.height + "; Screen.dpi = " + Screen.dpi);
        AdSize adSize = new AdSize(bannerWidth, bannerHeight);
        //int w = (int)(pixelsToBannerSize(Screen.width)) / 2 - (int)((bannerWidth) / 2);
        int w = (int)((Screen.width)) / 2 - (int)((bannerWidth) / 2);
        int h = Screen.height / 2 - bannerHeight / 2;
        Debug.Log("w = " + w + "; h = " + h);
        //_bannerView = new BannerView(_adUnitId, adSize, w, h);
        AdSize adaptiveSize =
                AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth);
        _bannerView = new BannerView(_adUnitId, adaptiveSize, pos);
        //_bannerView.SetPosition(Screen.width, Screen.height);
        Debug.Log("_bannerView.GetWidthInPixels() == " + _bannerView.GetWidthInPixels());
        Debug.Log("_bannerView.GetHeightInPixels() == " + _bannerView.GetHeightInPixels());
        Debug.Log("MobileAds.Utils.GetDeviceScale() = " + MobileAds.Utils.GetDeviceScale());
        ListenToAdEvents();
    }

    private void CreateBannerView(AdPosition pos, BannerAdSize adSize)
    {
        Debug.Log("Creating banner view");

        // If we already have a banner, destroy the old one.
        if (_bannerView != null)
        {
            DestroyAd();
        }
        AdSize size = AdSize.Banner;
        switch (adSize)
        {
            case BannerAdSize.Standard_320x50:
                size = AdSize.Banner;
                break;
            case BannerAdSize.Large_320x100:
                size = new AdSize(320, 100);
                break;
            case BannerAdSize.Adaptive:
                size = AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth);
                break;
        }
        _bannerView = new BannerView(_adUnitId, size, pos);
        ListenToAdEvents();
    }

    /// <summary>
    /// Creates the banner view and loads a banner ad.
    /// </summary>
    public void LoadAd(AdPosition pos)
    {
        // create an instance of a banner view first.
        if (_bannerView == null)
        {
            CreateBannerView(pos);
        }

        // create our request used to load the ad.
        var adRequest = new AdRequest();

        // send the request to load the ad.
        Debug.Log("Loading banner ad.");
        _bannerView.LoadAd(adRequest);

    }

    /// <summary>
    /// Creates the banner view and loads a banner ad.
    /// </summary>
    public void LoadAd(AdPosition pos, BannerAdSize adSize)
    {
        // create an instance of a banner view first.
        if (_bannerView == null)
        {
            CreateBannerView(pos, adSize);
        }

        // create our request used to load the ad.
        var adRequest = new AdRequest();

        // send the request to load the ad.
        Debug.Log("Loading banner ad.");
        _bannerView.LoadAd(adRequest);

    }

    /// <summary>
    /// Shows the ad.
    /// </summary>
    public void ShowAd()
    {
        if (_bannerView != null)
        {
            Debug.Log("Showing banner view.");
            _bannerView.Show();
        }
    }

    /// <summary>
    /// Hides the ad.
    /// </summary>
    public void HideAd()
    {
        if (_bannerView != null)
        {
            Debug.Log("Hiding banner view.");
            _bannerView.Hide();
        }
    }

    /// <summary>
    /// Destroys the banner view.
    /// </summary>
    public void DestroyAd()
    {
        if (_bannerView != null)
        {
            Debug.Log("Destroying banner view.");
            _bannerView.Destroy();
            _bannerView = null;
        }
        _isLoaded = false;
        if (where == BannerAdPlace.Home)
        {
            var onBannerAdLoadedEvent = new OnBannerAdLoadedEvent();
            onBannerAdLoadedEvent.isLoaded = false;
            EventManager.Instance.Raise(onBannerAdLoadedEvent);
        }
    }

    /// <summary>
    /// Logs the ResponseInfo.
    /// </summary>
    public void LogResponseInfo()
    {
        if (_bannerView != null)
        {
            var responseInfo = _bannerView.GetResponseInfo();
            if (responseInfo != null)
            {
                UnityEngine.Debug.Log(responseInfo);
            }
        }
    }

    public float GetBannerHeightInPixels()
    {
        if (_bannerView != null)
        {
            float h = _bannerView.GetHeightInPixels();
            return h;
        }
        return 0f;
    }

    /// <summary>
    /// listen to events the banner view may raise.
    /// </summary>
    private void ListenToAdEvents()
    {
        // Raised when an ad is loaded into the banner view.
        _bannerView.OnBannerAdLoaded += () =>
        {
            Debug.Log("Banner view loaded an ad with response : "
                      + _bannerView.GetResponseInfo());
            _isLoaded = true;
            if (where == BannerAdPlace.Home)
            {
                var onBannerAdLoadedEvent = new OnBannerAdLoadedEvent();
                onBannerAdLoadedEvent.isLoaded = true;
                EventManager.Instance.Raise(onBannerAdLoadedEvent);
            }
        };
        // Raised when an ad fails to load into the banner view.
        _bannerView.OnBannerAdLoadFailed += (LoadAdError error) =>
        {
            Debug.LogError("Banner view failed to load an ad with error : "
                           + error);
            _isLoaded = false;
            if (where == BannerAdPlace.Home)
            {
                var onBannerAdLoadedEvent = new OnBannerAdLoadedEvent();
                onBannerAdLoadedEvent.isLoaded = false;
                EventManager.Instance.Raise(onBannerAdLoadedEvent);
            }
        };
        // Raised when the ad is estimated to have earned money.
        _bannerView.OnAdPaid += (AdValue adValue) =>
        {
            Debug.Log(String.Format("Banner view paid {0} {1}.",
                adValue.Value,
                adValue.CurrencyCode));
        };
        // Raised when an impression is recorded for an ad.
        _bannerView.OnAdImpressionRecorded += () =>
        {
            Debug.Log("Banner view recorded an impression.");
        };
        // Raised when a click is recorded for an ad.
        _bannerView.OnAdClicked += () =>
        {
            Debug.Log("Banner view was clicked.");
        };
        // Raised when an ad opened full screen content.
        _bannerView.OnAdFullScreenContentOpened += () =>
        {
            Debug.Log("Banner view full screen content opened.");
        };
        // Raised when the ad closed full screen content.
        _bannerView.OnAdFullScreenContentClosed += () =>
        {
            Debug.Log("Banner view full screen content closed.");
        };
    }

    public void SetPlace(BannerAdPlace place)
    {
        where = place;
    }

    private static bool created;
    BannerView _bannerView;

    private bool _isLoaded;
    public bool IsLoaded { get => _isLoaded; }

    public BannerAdPlace where;
}
@NVentimiglia
Copy link
Member

@oskari-leppaaho

Could this be a race condition from other code setting _bannerView to null ? If so setting a local scoped variable should work.

void AddListeners(BannerView bannerView) {
// Existing coe on the local variable
}
void AddListeners() {
// Existing coe on the local variable
var bannerView = _bannerView;
}

That way the handlers will operate on a non-null same-instance reference.

@NVentimiglia NVentimiglia self-assigned this Jan 17, 2025
@NVentimiglia NVentimiglia added the Support General question, Installation question, or feedback. label Jan 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Support General question, Installation question, or feedback.
Projects
None yet
Development

No branches or pull requests

2 participants