using System.Collections.Generic; using GoogleMobileAds.Api; using System; using UnityEngine; using System.Linq; namespace WZ { public class AdmobBannerAdManager { private Dictionary _bannerAds = new Dictionary(); private Dictionary _retryCounters = new Dictionary(); private Dictionary _loadCallbacks = new Dictionary(); private Dictionary _adRevenueCache = new Dictionary(); private Dictionary _adStartLoadTimes = new Dictionary(); private BannerView _currentBannerView = null; public void InitializeAdUnits(BannerAlignType type, List adUnitIds) { foreach (var adUnitId in adUnitIds) { CreateRewardedAd(type, adUnitId); } } private void CreateRewardedAd(BannerAlignType type,string adUnitId) { if (string.IsNullOrEmpty(adUnitId)) return; if (_bannerAds.ContainsKey(adUnitId)) { LoggerUtils.Debug($"[Admob] banner Ad unit {adUnitId} already exists"); return; } var bannerAds = new BannerView(adUnitId, AdSize.Banner, type == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top); _adStartLoadTimes[adUnitId] = Time.realtimeSinceStartup; bannerAds.Hide(); _bannerAds[adUnitId] = bannerAds; _retryCounters[adUnitId] = 0; _adRevenueCache[adUnitId] = 0; bannerAds.OnBannerAdLoaded += () => { _retryCounters[adUnitId] = 0; _adRevenueCache[adUnitId] = AdmobUtils.GetBannerEcpm(bannerAds); LoggerUtils.Debug($"[Admob] banner -[Load]: {adUnitId} successfully, ecpm = {AdmobUtils.GetBannerEcpm(bannerAds)}"); AdsActionEvents.TrackAdLoaded(AdmobAdsManager.Instance.Platfrom, bannerAds?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "", adUnitId, AdsType.Banner, Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time) ? time : 0)); AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Banner); AdsActionEvents.TrackAdmobValue(PlatformType.Admob, bannerAds?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "", adUnitId, AdsType.Banner, AdmobUtils.GetBannerEcpm(bannerAds)); }; bannerAds.OnBannerAdLoadFailed += ((msg) => { if (!_retryCounters.TryAdd(adUnitId, 0)) { _retryCounters[adUnitId]++; } double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters.TryGetValue(adUnitId,out var times)? times : 0)); LoggerUtils.Debug($"[Admob] banner -[Load]: {adUnitId} failed, error message = {msg}"); // 延迟重试加载 _loadCallbacks[adUnitId] = () => LoadAd(adUnitId); _loadCallbacks.TryGetValue(adUnitId, out Action _loadCallback); if (_loadCallback != null) { TimerUtils.Instance.DelayExecute((float)retryDelay, () => _loadCallback?.Invoke()); } AdsActionEvents.TrackAdFailToLoad(AdmobAdsManager.Instance.Platfrom, "", "", AdsType.Banner,Time.realtimeSinceStartup - (_adStartLoadTimes.TryGetValue(adUnitId, out var time)? time : 0), msg.GetMessage()); }); bannerAds.OnAdPaid += ((adValue) => { LoggerUtils.Debug($"[Admob] banner -[interaction]: {adUnitId} show"); AdmobAdsManager.Instance.TrackAdImpression(bannerAds?.GetResponseInfo()?.GetLoadedAdapterResponseInfo().AdSourceName ?? "", bannerAds?.GetResponseInfo()?.GetLoadedAdapterResponseInfo().AdSourceInstanceId ?? "", adValue, AdsType.Banner, adUnitId); }); bannerAds.OnAdClicked += () => { AdsActionEvents.TrackAdClicked(AdmobAdsManager.Instance.Platfrom, bannerAds?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "", adUnitId, AdsType.Banner, "", AdmobUtils.GetBannerEcpm(bannerAds)); }; LoadAd(adUnitId); } public void LoadAd(string adUnitId) { if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId)) { return; } if (_bannerAds.TryGetValue(adUnitId, out var ad)) { ad.LoadAd(new AdRequest()); } } // 显示价格最高的广告 public void ShowHighestPayingAd(BannerAlignType bannerAlignType) { var highestPayingAdUnit = GetHighestPayingAdUnit(); if (!string.IsNullOrEmpty(highestPayingAdUnit)) { ShowAd(highestPayingAdUnit, bannerAlignType); } } public void HideBanner() { _currentBannerView?.Hide(); } // 显示特定广告位的广告 private void ShowAd(string adUnitId,BannerAlignType bannerAlignType) { if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Banner, adUnitId)) { return; } if (_bannerAds.TryGetValue(adUnitId, out var ad)) { ad.SetPosition(bannerAlignType == BannerAlignType.CenterBottom ? AdPosition.Bottom : AdPosition.Top); ad.Show(); _currentBannerView = ad; } } // 获取所有可用的广告位 public List GetAvailableAdUnits() { var available = new List(); foreach (var kvp in _bannerAds) { available.Add(kvp.Key); } return available; } // 获取特定广告位的收益信息 public double GetAdRevenue(string adUnitId) { if (_adRevenueCache.TryGetValue(adUnitId, out var revenue)) { return revenue; } return 0; } // 获取价格最高的广告位ID public string GetHighestPayingAdUnit() { if (_adRevenueCache.Count == 0) return null; return _adRevenueCache.OrderByDescending(kvp => kvp.Value).First().Key; } // 获取价格最高的广告收益信息 public double GetHighestPayingAdRevenue() { var highestPayingAdUnit = GetHighestPayingAdUnit(); if (!string.IsNullOrEmpty(highestPayingAdUnit) && _adRevenueCache.TryGetValue(highestPayingAdUnit, out var revenue)) { return revenue; } return 0; } // 清理资源 public void Destroy() { foreach (var ad in _bannerAds.Values) { ad.Destroy(); } _bannerAds.Clear(); _retryCounters.Clear(); _loadCallbacks.Clear(); _adRevenueCache.Clear(); } public void ClearAds(string[] adUnitIds) { // 将数组转换为HashSet以提高查找性能 HashSet validKeys = new HashSet(adUnitIds); // 收集需要移除的key List keysToRemove = new List(); foreach (var key in _bannerAds.Keys) { if (!validKeys.Contains(key)) { keysToRemove.Add(key); } } // 移除不在数组中的key foreach (string key in keysToRemove) { _bannerAds.Remove(key); _retryCounters.Remove(key); _loadCallbacks.Remove(key); _adRevenueCache.Remove(key); } } } }