using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Net.Security; using Firebase.Analytics; using UnityEngine; namespace WZ { public class MaxAdsManager : D_MonoSingleton, IAdService { public string ClientName => "AppLovin"; public PlatformType Platfrom => PlatformType.AppLovin; private string _max_app_key; // 广告单元ID字典,支持多个广告位 private List _maxInterstitialUnits = new List(); private List _maxRewardedUnits = new List(); // 广告信息字典,按广告位存储 private Dictionary _interAdInfos = new Dictionary(); private Dictionary _rewardAdInfos = new Dictionary(); // 重试次数字典,按广告位存储 private Dictionary _rewardRetryAttempts = new Dictionary(); private Dictionary _interRetryAttempts = new Dictionary(); // 加载时间字典,按广告位存储 private Dictionary _rvStartLoadTimes = new Dictionary(); private Dictionary _ivStartLoadTimes = new Dictionary(); private string _rvPos; private string _ivPos; private Action _rvCloseCallback = null; private Action _ivCloseCallback = null; private Action _rvShowFailedCallback = null; public bool _initialized { get; private set; } = false; private bool _receivedReward = false; public void Initialize() { _max_app_key = AdConfigParser.GetMaxAppKey(); if (string.IsNullOrEmpty(_max_app_key) || _initialized) return; LoggerUtils.Debug("[Max] init max"); // 关闭反转debug面板 MaxSdk.SetCreativeDebuggerEnabled(false); _maxInterstitialUnits = AdConfigParser.GetMaxAdUnits(AdsType.Interstitial); _maxRewardedUnits = AdConfigParser.GetMaxAdUnits(AdsType.Rewarded); InitRewardedCallback(); InitInterstitialCallback(); MaxSdkCallbacks.OnSdkInitializedEvent += (MaxSdkBase.SdkConfiguration obj) => { LoggerUtils.Debug("[Max] init max success"); }; MaxSdk.SetVerboseLogging(false); MaxSdk.SetSdkKey(_max_app_key); MaxSdk.InitializeSdk(); LoadRewarded(); LoadInterstitial(); _initialized = true; } public void RefreshAdsData() { _max_app_key = AdConfigParser.GetMaxAppKey(); _maxInterstitialUnits = AdConfigParser.GetMaxAdUnits(AdsType.Interstitial); _maxRewardedUnits = AdConfigParser.GetMaxAdUnits(AdsType.Rewarded); } #region 激励广告功能 private void InitRewardedCallback() { MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent; MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdLoadFailedEvent; MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += OnRewardedAdFailedToDisplayEvent; MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent += OnRewardedAdDisplayedEvent; MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent; MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdHiddenEvent; MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnRewardedRevenue; MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent; } public void LoadRewarded() { foreach (var kvp in _maxRewardedUnits) { LoggerUtils.Debug("[MAX] start load rewarded ad unit: "+kvp); LoadRewarded(kvp); } } private void LoadRewarded(string adUnitId) { if (!_maxRewardedUnits.Contains(adUnitId)) return; if (string.IsNullOrEmpty(adUnitId)) return; AdsActionEvents.TrackAdStartLoad(Platfrom, "", "", AdsType.Rewarded); MaxSdk.LoadRewardedAd(adUnitId); _rvStartLoadTimes[adUnitId] = Time.realtimeSinceStartup; // 初始化重试次数 if (!_rewardRetryAttempts.ContainsKey(adUnitId)) { _rewardRetryAttempts[adUnitId] = 0; } } public void DisplayRewarded(string adPos, Action rewardCallback = null, Action showFailedCallback = null) { _rvPos = adPos; _rvCloseCallback = rewardCallback; _rvShowFailedCallback = showFailedCallback; MaxSdk.ShowRewardedAd(GetHighestPayingAdUnit(AdsType.Rewarded)); } public double GetRewardedRevenue() { return GetHighestPayingAdRevenue(AdsType.Rewarded); } private double GetHighestPayingAdRevenue(AdsType adsType) { var highestPayingAdUnit = GetHighestPayingAdUnit(adsType); if (highestPayingAdUnit != null) { if (adsType == AdsType.Rewarded) { if (!_rewardAdInfos.TryGetValue(highestPayingAdUnit, out var adInfo)) { return -1; } return adInfo.Revenue; } else { if (!_interAdInfos.TryGetValue(highestPayingAdUnit, out var adInfo)) { return -1; } return adInfo.Revenue; } } return -1; } public string GetHighestPayingAdUnit(AdsType adsType) { string highestPayingAdUnit = null; double highestRevenue = -1; foreach (var kvp in adsType == AdsType.Rewarded ? _rewardAdInfos : _interAdInfos) { var adUnitId = kvp.Key; var revenue = kvp.Value.Revenue; if (IsAdsAvailable(adUnitId,adsType) && revenue > highestRevenue) { highestRevenue = revenue; highestPayingAdUnit = adUnitId; } } return highestPayingAdUnit; } public bool IsRewardedAvailable() { List availableAdUnits = new List(); foreach (var kvp in _maxRewardedUnits) { if (IsAdsAvailable(kvp, AdsType.Rewarded)) { availableAdUnits.Add(kvp); } } return availableAdUnits.Count > 0; } private bool IsAdsAvailable(string adUnit, AdsType adsType) { if (adsType == AdsType.Rewarded) { if (!_maxRewardedUnits.Contains(adUnit)) return false; return MaxSdk.IsRewardedAdReady(adUnit); } else { if (!_maxInterstitialUnits.Contains(adUnit)) return false; return MaxSdk.IsInterstitialReady(adUnit); } } private void OnRewardedRevenue(string adunit, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnRewardedRevenue network: " + adInfo.NetworkName + " revenue: " + adInfo.Revenue + " NetworkPlacement: " + adInfo.NetworkPlacement + " AdUnitIdentifier: " + adInfo.AdUnitIdentifier + " Placement: " + adInfo.Placement); TrackAdImpression(adInfo, AdsType.Rewarded); } private void OnRewardedAdLoadedEvent(string adunit, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnRewardedAdLoadedEvent network: " + adInfo.NetworkName + " revenue: " + adInfo.Revenue + " NetworkPlacement: " + adInfo.NetworkPlacement + " AdUnitIdentifier: " + adInfo.AdUnitIdentifier + " Placement: " + adInfo.Placement); AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Rewarded); _rewardAdInfos.TryAdd(adunit, adInfo); _rewardRetryAttempts.TryAdd(adunit, 0); AdsActionEvents.TrackAdLoaded(Platfrom, adInfo.NetworkName, adInfo.AdUnitIdentifier, AdsType.Rewarded, Time.realtimeSinceStartup - (_rvStartLoadTimes.TryGetValue(adunit, out var time) ? time : 0)); } private void OnRewardedAdLoadFailedEvent(string adunit, MaxSdkBase.ErrorInfo errorInfo) { LoggerUtils.Debug("[Max] OnRewardedAdLoadFailedEvent errorInfo" + errorInfo.Message); if (!_rewardRetryAttempts.TryAdd(adunit, 0)) { _rewardRetryAttempts[adunit]++; } double retryDelay = Math.Pow(2, Math.Min(6, _rewardRetryAttempts[adunit])); TimerUtils.Instance.DelayExecute((float)retryDelay, () => LoadRewarded(adunit)); AdsActionEvents.TrackAdFailToLoad(Platfrom, "", "", AdsType.Rewarded, Time.realtimeSinceStartup - (_rvStartLoadTimes.TryGetValue(adunit, out var time) ? time : 0), errorInfo.Message); } private void OnRewardedAdDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo info) { LoggerUtils.Debug("[Max] OnRewardedAdDisplayedEvent network: " + info.NetworkName + " revenue: " + info.Revenue + " NetworkPlacement: " + info.NetworkPlacement + " AdUnitIdentifier: " + info.AdUnitIdentifier + " Placement: " + info.Placement); } private void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnRewardedAdClickedEvent"); AdsActionEvents.TrackAdClicked(Platfrom,adInfo.NetworkName,adInfo.AdUnitIdentifier,AdsType.Rewarded,_rvPos,adInfo.Revenue); } private void OnRewardedAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnRewardedAdFailedToDisplayEvent :" + errorInfo.Message + " " + errorInfo.Code + " " + errorInfo.MediatedNetworkErrorMessage + " " + errorInfo.MediatedNetworkErrorCode); _rvShowFailedCallback?.Invoke(); _rvShowFailedCallback = null; if(_rewardAdInfos.ContainsKey(adUnitId))_rewardAdInfos.Remove(adUnitId); LoadRewarded(adUnitId); } private void OnRewardedAdHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) { _rvCloseCallback?.Invoke(_receivedReward,adInfo.Revenue); _rvCloseCallback = null; _receivedReward = false; if(_rewardAdInfos.ContainsKey(adUnitId))_rewardAdInfos.Remove(adUnitId); LoadRewarded(adUnitId); LoggerUtils.Debug("[Max] OnRewardedAdHiddenEvent "+_receivedReward); AdsActionEvents.TrackAdClosed(Platfrom,adInfo.NetworkName,adInfo.AdUnitIdentifier,AdsType.Rewarded,_rvPos,adInfo.Revenue); } private void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward, MaxSdkBase.AdInfo arg3) { LoggerUtils.Debug("[Max] OnRewardedAdReceivedRewardEvent network: " + arg3.NetworkName + " revenue: " + arg3.Revenue + " NetworkPlacement: " + arg3.NetworkPlacement + " AdUnitIdentifier: " + arg3.AdUnitIdentifier + " Placement: " + arg3.Placement); _receivedReward = true; } #endregion #region 插页广告功能 private void InitInterstitialCallback() { MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent; MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialLoadFailedEvent; MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += OnInterstitialAdFailedToDisplayEvent; MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialHiddenEvent; MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayedEvent; MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnInterstitialRevenue; MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickedEvent; } public void LoadInterstitial() { foreach (var kvp in _maxInterstitialUnits) { LoggerUtils.Debug("[MAX] start load inter ad unit: "+kvp); LoadInterstitial(kvp); } } public void LoadInterstitial(string adUnit) { if (!_maxInterstitialUnits.Contains(adUnit)) return; if (string.IsNullOrEmpty(adUnit)) return; MaxSdk.LoadInterstitial(adUnit); AdsActionEvents.TrackAdStartLoad(Platfrom, "", "", AdsType.Interstitial); _ivStartLoadTimes[adUnit] = Time.realtimeSinceStartup; // 初始化重试次数 if (!_interRetryAttempts.ContainsKey(adUnit)) { _interRetryAttempts[adUnit] = 0; } } public double GetInterstitialRevenue() { return GetHighestPayingAdRevenue(AdsType.Interstitial); } public void DisplayInterstitial(string ivPos, IvType _IvType = IvType.IV1, Action closeCallback = null) { _ivPos = ivPos; _ivCloseCallback = closeCallback; MaxSdk.ShowInterstitial(GetHighestPayingAdUnit(AdsType.Interstitial)); } public bool IsInterstitialAvailable() { List availableAdUnits = new List(); foreach (var kvp in _maxInterstitialUnits) { if (IsInterstitialAvailable(kvp)) { availableAdUnits.Add(kvp); } } return availableAdUnits.Count > 0; } public bool IsInterstitialAvailable(string adUnit) { return IsAdsAvailable(adUnit,AdsType.Interstitial); } private void OnInterstitialLoadedEvent(string adunit, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnInterstitialLoadedEvent network: " + adInfo.NetworkName + " revenue: " + adInfo.Revenue + " NetworkPlacement: " + adInfo.NetworkPlacement + " AdUnitIdentifier: " + adInfo.AdUnitIdentifier + " Placement: " + adInfo.Placement); AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Interstitial); _interRetryAttempts.TryAdd(adunit, 0); _interAdInfos.TryAdd(adunit, adInfo); AdsActionEvents.TrackAdLoaded(Platfrom, adInfo.NetworkName, adInfo.AdUnitIdentifier, AdsType.Interstitial, Time.realtimeSinceStartup - (_ivStartLoadTimes.TryGetValue(adunit, out var time) ? time : 0)); } private void OnInterstitialLoadFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo) { LoggerUtils.Debug("[Max] OnInterstitialLoadFailedEvent :" + errorInfo); if (!_interRetryAttempts.TryAdd(adUnitId, 0)) { _interRetryAttempts[adUnitId]++; } double retryDelay = Math.Pow(2, Math.Min(6, _interRetryAttempts[adUnitId])); TimerUtils.Instance.DelayExecute((float)retryDelay, () => LoadInterstitial(adUnitId)); AdsActionEvents.TrackAdFailToLoad(Platfrom, "", "", AdsType.Interstitial, Time.realtimeSinceStartup - (_ivStartLoadTimes.TryGetValue(adUnitId, out var time) ? time : 0), errorInfo.Message); } private void OnInterstitialAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo, MaxSdkBase.AdInfo arg3) { LoggerUtils.Debug("[Max] OnInterstitialAdFailedToDisplayEvent :" + errorInfo.Message + " " + errorInfo.Code + " " + errorInfo.MediatedNetworkErrorMessage + " " + errorInfo.MediatedNetworkErrorCode); _ivCloseCallback?.Invoke(0); _ivCloseCallback = null; if(_interAdInfos.ContainsKey(adUnitId))_interAdInfos.Remove(adUnitId); LoadInterstitial(adUnitId); } private void OnInterstitialDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo info) { LoggerUtils.Debug($"[Max] OnInterstitialDisplayedEvent network: {info.NetworkName}, revenue: {info.Revenue},NetworkPlacement: {info.NetworkPlacement}, AdUnitIdentifier: {info.AdUnitIdentifier},Placement: {info.Placement}"); } private void OnInterstitialHiddenEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug($"[Max] OnInterstitialHiddenEvent"); AdsActionEvents.TrackAdClosed(Platfrom,adInfo.NetworkName,adInfo.AdUnitIdentifier,AdsType.Interstitial, _ivPos,adInfo.Revenue); _ivCloseCallback?.Invoke(adInfo.Revenue); _ivCloseCallback = null; if(_interAdInfos.ContainsKey(adUnitId))_interAdInfos.Remove(adUnitId); LoadInterstitial(adUnitId); } private void OnInterstitialRevenue(string adunit, MaxSdkBase.AdInfo adInfo) { LoggerUtils.Debug("[Max] OnInterstitialRevenue network: " + adInfo.NetworkName + " revenue: " + adInfo.Revenue + " NetworkPlacement: " + adInfo.NetworkPlacement + " AdUnitIdentifier: " + adInfo.AdUnitIdentifier + " Placement: " + adInfo.Placement); TrackAdImpression(adInfo, AdsType.Interstitial); } private void OnInterstitialClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo) { AdsActionEvents.TrackAdClicked(Platfrom,adInfo.NetworkName,adInfo.AdUnitIdentifier,AdsType.Interstitial,_ivPos, adInfo.Revenue); } #endregion #region 开屏广告功能 public void LoadSplash() { } public bool IsSplashAvailable() { return false; } public void DisplaySplash() { } public double GetSplashRevenue() { return 0; } #endregion #region 原生广告功能 public void LoadNative() { } public bool IsNativeAvailable(string adUnitId) { return false; } public void DisplayNative(string _adPos, string adUnitId, NativeAdPosition position) { } public void RemoveNative(string adUnitId) { } public double GetNativeRevenue(string adUnitId) { return 0; } #endregion #region 横幅广告功能 public void LoadBanner() { } public bool IsBannerAvailable() { return false; } public void HideBanner() { } public double GetBannerRevenue() { return 0; } public void DisplayBanner() { } #endregion #region 广告收益上报 public void TrackAdImpression(MaxSdkBase.AdInfo adInfo, AdsType type) { AdjustTrackEvent.Instance.TrackAdEvent(adInfo.Revenue, adInfo.NetworkName, adInfo.AdUnitIdentifier, adInfo.Placement); FireBaseAnalyticsManager.Instance.OnAdRevenueEvent(ClientName, adInfo.NetworkName, adInfo.AdUnitIdentifier, type, adInfo.Revenue, type == AdsType.Rewarded ? _rvPos : _ivPos, AdPlayCountManager.GetAdsActionCount(type,AdPlayCountManager.PLAY_COUNT_SUFFIX)); ShuShuEvent.Instance.OnAdRevenueEvent(ClientName, adInfo.NetworkName, adInfo.AdUnitIdentifier, type.ToString(), adInfo.Revenue, type == AdsType.Rewarded ? _rvPos : _ivPos, AdPlayCountManager.GetAdsActionCount(type,AdPlayCountManager.PLAY_COUNT_SUFFIX)); } #endregion } }