| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  | using System; | 
					
						
							| 
									
										
										
										
											2025-08-30 13:48:51 +00:00
										 |  |  | using System.Collections; | 
					
						
							|  |  |  | using System.Collections.Generic; | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  | using System.Linq; | 
					
						
							|  |  |  | using GoogleMobileAds.Api; | 
					
						
							| 
									
										
										
										
											2025-08-30 13:48:51 +00:00
										 |  |  | using UnityEngine; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 10:32:50 +00:00
										 |  |  | namespace WZ | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     public class AdmobNativeAdManager | 
					
						
							| 
									
										
										
										
											2025-08-30 13:48:51 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |         private Dictionary<string, NativeOverlayAd> _nativeAds = new Dictionary<string, NativeOverlayAd>(); | 
					
						
							|  |  |  |         private Dictionary<string, double> _adRevenueCache = new Dictionary<string, double>(); | 
					
						
							|  |  |  |         private Dictionary<string, int> _retryCounters = new Dictionary<string, int>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public void InitializeAdUnits(List<string> adUnitIds) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             foreach (var adUnitId in adUnitIds) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 CreateNativeAd(adUnitId); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private void CreateNativeAd(string adUnitId) | 
					
						
							| 
									
										
										
										
											2025-08-31 13:19:46 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |             if (_nativeAds.ContainsKey(adUnitId)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} already exists"); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-08-30 13:48:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |             LoadAd(adUnitId); | 
					
						
							|  |  |  |             _adRevenueCache[adUnitId] = 0; | 
					
						
							| 
									
										
										
										
											2025-08-31 13:19:46 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |         public void LoadAd(string adUnitId) | 
					
						
							| 
									
										
										
										
											2025-08-31 13:19:46 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |             LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} load start"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             NativeOverlayAd.Load(adUnitId, new AdRequest(), new NativeAdOptions(), (NativeOverlayAd ad, LoadAdError error) => | 
					
						
							|  |  |  |             { | 
					
						
							| 
									
										
										
										
											2025-09-02 02:07:10 +00:00
										 |  |  |                 LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} loaded {ad} error {error}"); | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |                 if (error != null || ad == null) | 
					
						
							|  |  |  |                 { | 
					
						
							| 
									
										
										
										
											2025-09-02 02:07:10 +00:00
										 |  |  |                     if (!_retryCounters.TryAdd(adUnitId, 0)) | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         _retryCounters[adUnitId]++; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |                     var retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId])); | 
					
						
							|  |  |  |                     TimerUtils.Instance.DelayExecute((float)retryDelay, () => { LoadAd(adUnitId); }); | 
					
						
							|  |  |  |                     LoggerUtils.Debug("[Admob] Native ad failed to load an ad with error : " + error + " \n retryDelay :" + retryDelay); | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 _retryCounters[adUnitId] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 LoggerUtils.Debug("Admob Native ad loaded with response : " + ad.GetResponseInfo().ToString()); | 
					
						
							|  |  |  |                 _nativeAds[adUnitId] = ad; | 
					
						
							|  |  |  |                 _adRevenueCache[adUnitId] = AdmobUtils.GetNativeEcpm(ad); | 
					
						
							|  |  |  |                 AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Native); | 
					
						
							| 
									
										
										
										
											2025-08-31 13:19:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |                 ad.OnAdPaid += (AdValue adValue) => | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     LoggerUtils.Debug($"[Admob] Native ad paid {adValue.Value} {adValue.CurrencyCode}."); | 
					
						
							|  |  |  |                     AdmobAdsManager.Instance.TrackAdImpression(ad.GetResponseInfo().GetLoadedAdapterResponseInfo(), | 
					
						
							|  |  |  |                         adValue, | 
					
						
							|  |  |  |                         AdsType.Native, | 
					
						
							|  |  |  |                         AdmobUtils.ParseResponseInfo(ad.GetResponseInfo())); | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ad.OnAdImpressionRecorded += () => { LoggerUtils.Debug("[Admob] Native ad recorded an impression."); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ad.OnAdClicked += () => { LoggerUtils.Debug("[Admob] Native ad was clicked."); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ad.OnAdFullScreenContentOpened += () => { LoggerUtils.Debug("[Admob] Native ad full screen content opened."); }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ad.OnAdFullScreenContentClosed += () => { LoggerUtils.Debug("[Admob] Native ad full screen content closed."); }; | 
					
						
							|  |  |  |             }); | 
					
						
							| 
									
										
										
										
											2025-08-31 13:19:46 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |         // 显示价格最高的广告 | 
					
						
							|  |  |  |         public void ShowHighestPayingAd(NativeAdPosition position) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             LoggerUtils.Debug($"[Admob] Native ad ShowHighestPayingAd {position}"); | 
					
						
							|  |  |  |             var highestPayingAdUnit = GetHighestPayingAdUnit(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             LoggerUtils.Debug($"[Admob] Native ad ShowHighestPayingAd {position} , highestPayingAdUnit = {highestPayingAdUnit}"); | 
					
						
							|  |  |  |             if (!string.IsNullOrEmpty(highestPayingAdUnit)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ShowAd(position, highestPayingAdUnit); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 显示特定广告位的广告 | 
					
						
							|  |  |  |         public void ShowAd(NativeAdPosition position, string adUnitId) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             LoggerUtils.Debug($"[Admob] Native ad ShowAd start {adUnitId} , {position}"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (_nativeAds.TryGetValue(adUnitId, out var ad)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 LoggerUtils.Debug($"[Admob] Native ad ShowAd end {adUnitId} , {position}"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Define a native template style with a custom style. | 
					
						
							|  |  |  |                 var style = position.NativeTemplateStyle ?? new NativeTemplateStyle() | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     TemplateId = NativeTemplateId.Medium, | 
					
						
							|  |  |  |                     // TemplateId = "big" | 
					
						
							|  |  |  |                     //  MainBackgroundColor = Color.green, | 
					
						
							|  |  |  |                     CallToActionText = new NativeTemplateTextStyle() | 
					
						
							|  |  |  |                     { | 
					
						
							|  |  |  |                         FontSize = 9, | 
					
						
							|  |  |  |                         Style = NativeTemplateFontStyle.Bold | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // Renders a native overlay ad at the default size | 
					
						
							|  |  |  |                 // and anchored to the bottom of the screne. | 
					
						
							|  |  |  |                 ad.RenderTemplate(style, new AdSize(position.Width, position.Height), position.X, position.Y); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 ad.Show(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 检查特定广告位是否可用 | 
					
						
							| 
									
										
										
										
											2025-09-02 02:07:10 +00:00
										 |  |  |         public bool IsAdAvailable(string adUnitId) | 
					
						
							| 
									
										
										
										
											2025-09-01 15:57:10 +00:00
										 |  |  |         { | 
					
						
							|  |  |  |             return _nativeAds.TryGetValue(adUnitId, out _); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 获取所有可用的广告位 | 
					
						
							|  |  |  |         public List<string> GetAvailableAdUnits() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             return _nativeAds.Select(kvp => kvp.Key).ToList(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 获取价格最高的广告位ID | 
					
						
							|  |  |  |         public string GetHighestPayingAdUnit() | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             string highestPayingAdUnit = null; | 
					
						
							|  |  |  |             double highestRevenue = -1; | 
					
						
							|  |  |  |             LoggerUtils.Debug($"[Admob] Native ad GetHighestPayingAdUnit {_adRevenueCache.Count}"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             foreach (var kvp in _adRevenueCache) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var adUnitId = kvp.Key; | 
					
						
							|  |  |  |                 var revenue = kvp.Value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // 确保广告确实已加载并且价格更高 | 
					
						
							|  |  |  |                 if (IsAdAvailable(adUnitId) && revenue > highestRevenue) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     highestRevenue = revenue; | 
					
						
							|  |  |  |                     highestPayingAdUnit = adUnitId; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             return highestPayingAdUnit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // 获取价格最高的广告收益信息 | 
					
						
							|  |  |  |         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 _nativeAds.Values) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 ad.Destroy(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             _nativeAds.Clear(); | 
					
						
							|  |  |  |             _adRevenueCache.Clear(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         public void RemoveNative(string adUnitId) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (adUnitId == null || string.IsNullOrEmpty(adUnitId)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 foreach (var ad in _nativeAds.Values) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     ad.Hide(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (_nativeAds.TryGetValue(adUnitId, out var tempAd)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 tempAd.Hide(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |