diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager.meta new file mode 100644 index 0000000..371ca8a --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5655f7ecd943148c084f4b9e672cae8e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs new file mode 100644 index 0000000..77af5ab --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs @@ -0,0 +1,341 @@ +using System.Collections.Generic; +using GoogleMobileAds.Api; +using Script.Common; +using Script.SDKManager.AdsSDKManager.Utils; +using Script.Utils; +using SDK.Utils; +using SDKManager.AdsSDKManager.Constant; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager +{ + + public class AdmobAdsManager : NormalSingleton, IAdService + { + public string ClientName => "Admob"; + private AdmobBannerAdManager _admobBannerAdManager; + private AdmobInterstitialAdManager _admobInterstitialAdManager; + private AdmobRewardedAdManager _admobRewardedAdManager; + private AdmobNativeAdManager _admobNativeAdManager; + private AdmobSplashAdManager _admobSplashAdManager; + private List _interstitialAdUnits; + private List _rewardedAdUnits; + private List _nativeAdUnits; + private List _splashAdUnits; + private List _bannerAdUnits; + private bool _initialized; + + + public void Initialize() + { + MobileAds.RaiseAdEventsOnUnityMainThread = true; + _bannerAdUnits = AdConfigParser.GetAdmobAdUnits(AdsType.Banner); + MobileAds.Initialize(initStatus => + { + if (_bannerAdUnits.Count > 0) + { + _admobBannerAdManager = new AdmobBannerAdManager(); + _admobBannerAdManager.InitializeAdUnits(BannerAliignType.BannerCenterBottomAlign, + _bannerAdUnits, + OnBannerAdLoaded, + OnBannerAdLoadFailed, + OnBannerAdPaid, + OnBannerAdClicked + ); + } + if (_interstitialAdUnits.Count > 0) LoadInterstitial(); + if (_rewardedAdUnits.Count > 0) LoadRewarded(); + + LoadSplash(); + _initialized = true; + LoggerUtils.Debug("[Admob] init success"); + }); + + } + + #region 激励广告功能 + public void LoadRewarded() + { + _admobRewardedAdManager = new AdmobRewardedAdManager(); + _admobRewardedAdManager.Destroy(); + _admobRewardedAdManager.InitializeAdUnits( + _rewardedAdUnits, + OnRewardedAdLoaded, + OnRewardedAdLoadFailed, + OnRewardedAdShowed, + OnRewardedAdDismissed, + OnRewardedAdError, + OnRewardAdPaid, + OnRewardedAdClicked + ); + } + public void DisplayRewarded() + { + _admobRewardedAdManager.ShowHighestPayingAd(); + } + + public double GetRewardedRevenue() + { + return _admobRewardedAdManager.GetHighestPayingAdRevenue(); + } + + public bool IsRewardedAvailable() + { + if (!_initialized) return false; + return _admobRewardedAdManager.GetAvailableAdUnits().Count > 0; + } + + private void OnRewardedAdLoaded(string adUnitId) + { + + } + + private void OnRewardedAdLoadFailed(string adUnitId, int errorCode, string errorMsg) + { + + } + + private void OnRewardedAdShowed(string adUnitId) + { + + } + + private void OnRewardedAdDismissed(string adUnitId) + { + + + } + + private void OnRewardedAdError(string adUnitId, int errorCode, string errorMsg) + { + + } + + private void OnRewardedAdClicked(string adUnitId) + { + + } + + private void OnRewardAdPaid(AdValue adValue) + { + + + } + #endregion + + #region 插页广告功能 + public void LoadInterstitial() + { + _admobInterstitialAdManager = new AdmobInterstitialAdManager(); + _admobInterstitialAdManager.Destroy(); + _admobInterstitialAdManager.InitializeAdUnits( + _interstitialAdUnits, + OnInterstitialAdLoaded, + OnInterstitialAdLoadFailed, + OnInterstitialAdShowed, + OnInterstitialAdDismissed, + OnInterstitialAdError, + OnInterstitialAdPaid, + OnInterstitialAdClicked + ); + } + public double GetInterstitialRevenue() + { + return _admobInterstitialAdManager.GetHighestPayingAdRevenue(); + } + + public void DisplayInterstitial() + { + _admobInterstitialAdManager.ShowHighestPayingAd(); + } + + public bool IsInterstitialAvailable() + { + if (!_initialized) return false; + return _admobInterstitialAdManager.GetAvailableAdUnits().Count > 0; + } + + private void OnInterstitialAdLoaded(string adUnitId) + { + + } + + private void OnInterstitialAdLoadFailed(string adUnitId, int errorCode, string errorMsg) + { + + } + private void OnInterstitialAdClicked(string adUnitId) + { + + } + + private void OnInterstitialAdPaid(AdValue adValue) + { + + } + + private void OnInterstitialAdShowed(string adUnitId) + { + + } + + private void OnInterstitialAdDismissed(string adUnitId) + { + + } + + private void OnInterstitialAdError(string adUnitId, int errorCode, string errorMsg) + { + + } + #endregion + + + + #region 开屏广告功能 + public void LoadSplash() + { + _admobSplashAdManager = new AdmobSplashAdManager(); + _admobSplashAdManager.Destroy(); + _admobSplashAdManager.InitializeAdUnits( + _splashAdUnits, + OnSplashAdLoaded, + OnSplashAdLoadFailed, + OnSplashAdShowed, + OnSplashAdDismissed, + OnSplashAdError, + OnSplashAdPaid, + OnSplashAdClicked + ); + } + + public bool IsSplashAvailable() + { + return _admobBannerAdManager.GetAvailableAdUnits().Count > 0; + } + public void DisplaySplash() + { + _admobSplashAdManager.ShowHighestPayingAd(); + } + + public double GetSplashRevenue() + { + return _admobSplashAdManager.GetHighestPayingAdRevenue(); + } + + private void OnSplashAdLoaded(string adUnitId) + { + + } + + private void OnSplashAdLoadFailed(string adUnitId, int errorCode, string errorMsg) + { + + } + + private void OnSplashAdShowed(string adUnitId) + { + + } + + private void OnSplashAdDismissed(string adUnitId) + { + } + + private void OnSplashAdError(string adUnitId, int errorCode, string errorMsg) + { + + } + + private void OnSplashAdClicked(string adUnitId) + { + + + } + + private void OnSplashAdPaid(AdValue adValue) + { + + } + + + #endregion + + #region 原生广告功能 + public void LoadNative() + { + throw new System.NotImplementedException(); + } + public double GetNativeRevenue() + { + return 0; + } + public void DisplayNative(NativeAdPosition position) + { + + } + + public bool IsNativeAvailable() + { + return false; + } + + public void RemoveNative() + { + + } + #endregion + + #region 横幅广告功能 + public void LoadBanner() + { + foreach (var adUnitId in _bannerAdUnits) + { + _admobBannerAdManager.LoadAd(adUnitId); + } + } + + public bool IsBannerAvailable() + { + return _admobBannerAdManager.GetAvailableAdUnits().Count > 0; + } + public void HideBanner() + { + _admobBannerAdManager.HideBanner(); + } + + public double GetBannerRevenue() + { + return _admobBannerAdManager.GetHighestPayingAdRevenue(); + } + + public void DisplayBanner() + { + _admobBannerAdManager.ShowHighestPayingAd(); + } + + private void OnBannerAdLoaded(string adUnitId) + { + + + } + + private void OnBannerAdLoadFailed(string adUnitId, int errorCode, string errorMsg) + { + + } + + private void OnBannerAdClicked() + { + + } + + private void OnBannerAdPaid(AdValue adValue) + { + + } + #endregion + + } + +} + diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs.meta new file mode 100644 index 0000000..b308fc5 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobAdsManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 7b60d6c8a08c64629a3ae1a20bb7acbc \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs new file mode 100644 index 0000000..d16bfcf --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs @@ -0,0 +1,186 @@ +using System.Collections.Generic; +using GoogleMobileAds.Api; +using System; +using Script.Utils; +using SDKManager.AdsSDKManager.Constant; +using Script.SDKManager.AdsSDKManager.AdmobAdsManager.Utils; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager +{ + public class AdmobBannerAdManager + { + private Dictionary _bannerAds = new Dictionary(); + private Dictionary _retryCounters = new Dictionary(); + private Dictionary _loadCallbacks = new Dictionary(); + private Dictionary _adRevenueCache = new Dictionary(); + + public void InitializeAdUnits(BannerAliignType type, List adUnitIds, + Action onAdLoaded = null, + Action onAdLoadFailed = null, + Action OnAdPaid = null, + Action onAdClicked = null) + { + foreach (var adUnitId in adUnitIds) + { + CreateRewardedAd(type, adUnitId, onAdLoaded, onAdLoadFailed,OnAdPaid, onAdClicked); + } + } + + private void CreateRewardedAd(BannerAliignType type,string adUnitId, Action onAdLoaded, + Action onAdLoadFailed, + Action OnAdPaid, + Action onAdClicked) + { + if (_bannerAds.ContainsKey(adUnitId)) + { + LoggerUtils.Debug($"Bigo banner Ad unit {adUnitId} already exists"); + return; + } + + var bannerAds = new BannerView(adUnitId, AdSize.Banner, type == BannerAliignType.BannerCenterBottomAlign ? AdPosition.Bottom : AdPosition.Top); + _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"); + onAdLoaded?.Invoke(adUnitId); + }; + + bannerAds.OnBannerAdLoadFailed += ((msg) => + { + _retryCounters[adUnitId]++; + double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId])); + LoggerUtils.Debug($"[Admob] banner -[Load]: {adUnitId} failed, error message = {msg}"); + + // 延迟重试加载 + _loadCallbacks[adUnitId] = () => LoadAd(adUnitId); + TimerUtils.DelayExecute((float)retryDelay, () => _loadCallbacks[adUnitId]?.Invoke()); + onAdLoadFailed?.Invoke(adUnitId, msg.GetCode(), msg.GetMessage()); + }); + + bannerAds.OnAdPaid += ((adValue) => + { + LoggerUtils.Debug($"[Admob] banner -[interaction]: {adUnitId} show"); + OnAdPaid?.Invoke(adValue); + }); + + bannerAds.OnAdClicked += () => + { + onAdClicked?.Invoke(); + }; + LoadAd(adUnitId); + } + + public void LoadAd(string adUnitId) + { + if (_bannerAds.TryGetValue(adUnitId, out var ad)) + { + ad.LoadAd(new AdRequest()); + } + } + + // 显示价格最高的广告 + public void ShowHighestPayingAd() + { + var highestPayingAdUnit = GetHighestPayingAdUnit(); + if (!string.IsNullOrEmpty(highestPayingAdUnit)) + { + ShowAd(highestPayingAdUnit); + } + } + + public void HideBanner() + { + + var highestPayingAdUnit = GetHighestPayingAdUnit(); + if (!string.IsNullOrEmpty(highestPayingAdUnit)) + { + if (_bannerAds.TryGetValue(highestPayingAdUnit, out var ad)) + { + ad.Hide(); + } + } + } + // 显示特定广告位的广告 + private void ShowAd(string adUnitId) + { + if (_bannerAds.TryGetValue(adUnitId, out var ad)) + { + ad.Show(); + } + } + + // 获取所有可用的广告位 + 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() + { + string highestPayingAdUnit = null; + double highestRevenue = 0; + + foreach (var kvp in _adRevenueCache) + { + var adUnitId = kvp.Key; + var revenue = kvp.Value; + + // 确保广告确实已加载并且价格更高 + if (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 _bannerAds.Values) + { + ad.Destroy(); + } + _bannerAds.Clear(); + _retryCounters.Clear(); + _loadCallbacks.Clear(); + _adRevenueCache.Clear(); + } + } +} + diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs.meta new file mode 100644 index 0000000..9c1be83 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobBannerAdManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 64f1fb952d2214082b5d90c7c1b114f5 \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs new file mode 100644 index 0000000..743c3fc --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using GoogleMobileAds.Api; +using Script.SDKManager.AdsSDKManager.AdmobAdsManager.Utils; +using Script.Utils; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager +{ + public class AdmobInterstitialAdManager + { + private Dictionary _interstitialAds = new Dictionary(); + private Dictionary _adRevenueCache = new Dictionary(); + + public void InitializeAdUnits(List adUnitIds, Action onAdLoaded = null, + Action onAdLoadFailed = null, + Action onAdShowed = null, + Action onAdDismissed = null, + Action onAdError = null, + Action onAdPaid = null, + Action onAdClicked = null) + { + foreach (var adUnitId in adUnitIds) + { + CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError,onAdPaid, onAdClicked); + } + } + + private void CreateRewardedAd(string adUnitId, Action onAdLoaded, + Action onAdLoadFailed, + Action onAdShowed, + Action onAdDismissed, + Action onAdError, + Action onAdPaid, + Action onAdClicked) + { + if (_interstitialAds.ContainsKey(adUnitId)) + { + LoggerUtils.Debug($"[Admob] Interstitial Ad unit {adUnitId} already exists"); + return; + } + _adRevenueCache[adUnitId] = 0; + + InterstitialAd.Load(adUnitId, new AdRequest(), (InterstitialAd ad, LoadAdError error) => + { + if (error != null || ad == null) + { + LoggerUtils.Debug("[Admob] interstitial ad failed to load an ad with error : " + error); + onAdLoadFailed?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + return; + } + + LoggerUtils.Debug("Admob Interstitial ad loaded with response : " + ad.GetResponseInfo().ToString()); + _interstitialAds[adUnitId] = ad; + _adRevenueCache[adUnitId] = AdmobUtils.GetInterstitialAdEcpm(ad); + onAdLoaded?.Invoke(adUnitId); + + ad.OnAdPaid += (AdValue adValue) => + { + LoggerUtils.Debug(String.Format("[Admob] Interstitial ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + // ivRevenue = adValue.Value / 1000000f; + onAdPaid?.Invoke(adValue); + }; + + ad.OnAdImpressionRecorded += () => + { + LoggerUtils.Debug("[Admob] Interstitial ad recorded an impression."); + }; + + ad.OnAdClicked += () => + { + LoggerUtils.Debug("[Admob] Interstitial ad was clicked."); + onAdClicked?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentOpened += () => + { + LoggerUtils.Debug("[Admob] Interstitial ad full screen content opened."); + onAdShowed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentClosed += () => + { + LoggerUtils.Debug("[Admob] Interstitial ad full screen content closed."); + onAdDismissed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentFailed += (AdError error) => + { + LoggerUtils.Debug("[Admob] Interstitial ad failed to open full screen content with error : " + error); + onAdError?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + }; + }); + } + + public void LoadAd(string adUnitId) + { + + } + + // 显示价格最高的广告 + public void ShowHighestPayingAd() + { + var highestPayingAdUnit = GetHighestPayingAdUnit(); + if (!string.IsNullOrEmpty(highestPayingAdUnit)) + { + ShowAd(highestPayingAdUnit); + } + } + + // 显示特定广告位的广告 + private void ShowAd(string adUnitId) + { + if (_interstitialAds.TryGetValue(adUnitId, out var ad)) + { + ad.Show(); + } + } + + + // 检查特定广告位是否可用 + private bool IsAdAvailable(string adUnitId) + { + return _interstitialAds.TryGetValue(adUnitId, out var ad) && ad.CanShowAd(); + } + + // 获取所有可用的广告位 + public List GetAvailableAdUnits() + { + var available = new List(); + foreach (var kvp in _interstitialAds) + { + if (kvp.Value.CanShowAd()) + { + available.Add(kvp.Key); + } + } + return available; + } + + // 获取价格最高的广告位ID + public string GetHighestPayingAdUnit() + { + string highestPayingAdUnit = null; + double highestRevenue = 0; + + 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 _interstitialAds.Values) + { + ad.Destroy(); + } + _interstitialAds.Clear(); + _adRevenueCache.Clear(); + } + } +} diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs.meta new file mode 100644 index 0000000..2a476a8 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobInterstitialAdManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 836d77072fa604c0480097316bb1aabe \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs new file mode 100644 index 0000000..48726c6 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class AdmobNativeAdManager : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs.meta new file mode 100644 index 0000000..bf4541e --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 5421cfa6befcb4e48a4361180aa3c8ff \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs new file mode 100644 index 0000000..24fe01f --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using GoogleMobileAds.Api; +using Script.SDKManager.AdsSDKManager.AdmobAdsManager.Utils; +using Script.Utils; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager +{ + public class AdmobRewardedAdManager + { + private Dictionary _rewardedAds = new Dictionary(); + private Dictionary _adRevenueCache = new Dictionary(); + + public void InitializeAdUnits(List adUnitIds, Action onAdLoaded = null, + Action onAdLoadFailed = null, + Action onAdShowed = null, + Action onAdDismissed = null, + Action onAdError = null, + Action onAdPaid = null, + Action onAdClicked = null) + { + foreach (var adUnitId in adUnitIds) + { + CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError,onAdPaid, onAdClicked); + } + } + + private void CreateRewardedAd(string adUnitId, Action onAdLoaded, + Action onAdLoadFailed, + Action onAdShowed, + Action onAdDismissed, + Action onAdError, + Action onAdPaid, + Action onAdClicked) + { + if (_rewardedAds.ContainsKey(adUnitId)) + { + LoggerUtils.Debug($"[Admob] rewarded Ad unit {adUnitId} already exists"); + return; + } + _adRevenueCache[adUnitId] = 0; + + RewardedAd.Load(adUnitId, new AdRequest(), (RewardedAd ad, LoadAdError error) => + { + if (error != null || ad == null) + { + LoggerUtils.Debug("[Admob] rewarded ad failed to load an ad with error : " + error); + onAdLoadFailed?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + return; + } + + LoggerUtils.Debug("[Admob] rewarded ad loaded with response : " + ad.GetResponseInfo().ToString()); + _rewardedAds[adUnitId] = ad; + _adRevenueCache[adUnitId] = AdmobUtils.GetRewardedAdEcpm(ad); + onAdLoaded?.Invoke(adUnitId); + + ad.OnAdPaid += (AdValue adValue) => + { + LoggerUtils.Debug(String.Format("[Admob] rewarded ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + // ivRevenue = adValue.Value / 1000000f; + onAdPaid?.Invoke(adValue); + }; + + ad.OnAdImpressionRecorded += () => + { + LoggerUtils.Debug("[Admob] rewarded ad recorded an impression."); + }; + + ad.OnAdClicked += () => + { + LoggerUtils.Debug("[Admob] rewarded ad was clicked."); + onAdClicked?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentOpened += () => + { + LoggerUtils.Debug("[Admob] rewarded ad full screen content opened."); + onAdShowed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentClosed += () => + { + LoggerUtils.Debug("[Admob] rewarded ad full screen content closed."); + onAdDismissed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentFailed += (AdError error) => + { + LoggerUtils.Debug("[Admob] rewarded ad failed to open full screen content with error : " + error); + onAdError?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + }; + }); + } + + // 显示价格最高的广告 + public void ShowHighestPayingAd() + { + var highestPayingAdUnit = GetHighestPayingAdUnit(); + if (!string.IsNullOrEmpty(highestPayingAdUnit)) + { + ShowAd(highestPayingAdUnit); + } + } + + // 显示特定广告位的广告 + private void ShowAd(string adUnitId) + { + if (_rewardedAds.TryGetValue(adUnitId, out var ad)) + { + ad.Show(null); + } + } + + + // 检查特定广告位是否可用 + private bool IsAdAvailable(string adUnitId) + { + return _rewardedAds.TryGetValue(adUnitId, out var ad) && ad.CanShowAd(); + } + + // 获取所有可用的广告位 + public List GetAvailableAdUnits() + { + var available = new List(); + foreach (var kvp in _rewardedAds) + { + if (kvp.Value.CanShowAd()) + { + available.Add(kvp.Key); + } + } + return available; + } + + // 获取价格最高的广告位ID + public string GetHighestPayingAdUnit() + { + string highestPayingAdUnit = null; + double highestRevenue = 0; + + 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 _rewardedAds.Values) + { + ad.Destroy(); + } + _rewardedAds.Clear(); + _adRevenueCache.Clear(); + } + } +} diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs.meta new file mode 100644 index 0000000..46664d2 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobRewardedAdManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 8a66ed9c6ea4e42e5a057855d6888b3c \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs new file mode 100644 index 0000000..de1b16e --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using GoogleMobileAds.Api; +using Script.SDKManager.AdsSDKManager.AdmobAdsManager.Utils; +using Script.Utils; +using UnityEngine; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager +{ + public class AdmobSplashAdManager + { + private Dictionary _appOpenAds = new Dictionary(); + private Dictionary _adRevenueCache = new Dictionary(); + + public void InitializeAdUnits(List adUnitIds, Action onAdLoaded = null, + Action onAdLoadFailed = null, + Action onAdShowed = null, + Action onAdDismissed = null, + Action onAdError = null, + Action onAdPaid = null, + Action onAdClicked = null) + { + foreach (var adUnitId in adUnitIds) + { + CreateappopenAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError,onAdPaid, onAdClicked); + } + } + + private void CreateappopenAd(string adUnitId, Action onAdLoaded, + Action onAdLoadFailed, + Action onAdShowed, + Action onAdDismissed, + Action onAdError, + Action onAdPaid, + Action onAdClicked) + { + if (_appOpenAds.ContainsKey(adUnitId)) + { + LoggerUtils.Debug($"[Admob] appopen Ad unit {adUnitId} already exists"); + return; + } + _adRevenueCache[adUnitId] = 0; + + AppOpenAd.Load(adUnitId, new AdRequest(), (AppOpenAd ad, LoadAdError error) => + { + if (error != null || ad == null) + { + LoggerUtils.Debug("[Admob] appopen ad failed to load an ad with error : " + error); + onAdLoadFailed?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + return; + } + + LoggerUtils.Debug("[Admob] appopen ad loaded with response : " + ad.GetResponseInfo().ToString()); + _appOpenAds[adUnitId] = ad; + _adRevenueCache[adUnitId] = AdmobUtils.GetAppOpenAdEcpm(ad); + onAdLoaded?.Invoke(adUnitId); + + ad.OnAdPaid += (AdValue adValue) => + { + LoggerUtils.Debug(String.Format("[Admob] appopen ad paid {0} {1}.", adValue.Value, adValue.CurrencyCode)); + // ivRevenue = adValue.Value / 1000000f; + onAdPaid?.Invoke(adValue); + }; + + ad.OnAdImpressionRecorded += () => + { + LoggerUtils.Debug("[Admob] appopen ad recorded an impression."); + }; + + ad.OnAdClicked += () => + { + LoggerUtils.Debug("[Admob] appopen ad was clicked."); + onAdClicked?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentOpened += () => + { + LoggerUtils.Debug("[Admob] appopen ad full screen content opened."); + onAdShowed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentClosed += () => + { + LoggerUtils.Debug("[Admob] appopen ad full screen content closed."); + onAdDismissed?.Invoke(adUnitId); + }; + + ad.OnAdFullScreenContentFailed += (AdError error) => + { + LoggerUtils.Debug("[Admob] appopen ad failed to open full screen content with error : " + error); + onAdError?.Invoke(adUnitId, error.GetCode(), error.GetMessage()); + }; + }); + } + + // 显示价格最高的广告 + public void ShowHighestPayingAd() + { + var highestPayingAdUnit = GetHighestPayingAdUnit(); + if (!string.IsNullOrEmpty(highestPayingAdUnit)) + { + ShowAd(highestPayingAdUnit); + } + } + + // 显示特定广告位的广告 + private void ShowAd(string adUnitId) + { + if (_appOpenAds.TryGetValue(adUnitId, out var ad)) + { + ad.Show(); + } + } + + + // 检查特定广告位是否可用 + private bool IsAdAvailable(string adUnitId) + { + return _appOpenAds.TryGetValue(adUnitId, out var ad) && ad.CanShowAd(); + } + + // 获取所有可用的广告位 + public List GetAvailableAdUnits() + { + var available = new List(); + foreach (var kvp in _appOpenAds) + { + if (kvp.Value.CanShowAd()) + { + available.Add(kvp.Key); + } + } + return available; + } + + // 获取价格最高的广告位ID + public string GetHighestPayingAdUnit() + { + string highestPayingAdUnit = null; + double highestRevenue = 0; + + 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 _appOpenAds.Values) + { + ad.Destroy(); + } + _appOpenAds.Clear(); + _adRevenueCache.Clear(); + } + } +} \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs.meta new file mode 100644 index 0000000..6eb262f --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobSplashAdManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 137bc68f35e5e4e9383ffd94f745c1bd \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils.meta new file mode 100644 index 0000000..66a8aef --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e4138f3b033334c7cb1fca3762291240 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs new file mode 100644 index 0000000..45e3867 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs @@ -0,0 +1,125 @@ +using System; +using System.Linq; +using System.Reflection; +using GoogleMobileAds.Api; +using Script.Utils; +using UnityEngine; + +namespace Script.SDKManager.AdsSDKManager.AdmobAdsManager.Utils +{ + public class AdmobUtils + { + public static double GetBannerEcpm(BannerView bannerView) + { + return GetEcpm(bannerView, "bannerView", "adView", BannerStack); + } + + public static double GetRewardedAdEcpm(RewardedAd rewardedAd) + { + return GetEcpm(rewardedAd, "androidRewardedAd", "rewardedAd", RvStack); + } + + public static double GetInterstitialAdEcpm(InterstitialAd interstitialAd) + { + return GetEcpm(interstitialAd, "androidInterstitialAd", "interstitialAd", IvStack); + } + + public static double GetAppOpenAdEcpm(AppOpenAd appOpenAd) + { + return GetEcpm(appOpenAd, "androidAppOpenAd", "appOpenAd", SpStack); + } + + private static double GetEcpm(object o, string cShapeFieldName, string javaFieldName, string[] stack) + { + try + { + return GetEcpm(GetAdValue(GetJavaAdViewOjb(o, cShapeFieldName, javaFieldName), stack)); + } + catch (Exception e) + { + LoggerUtils.Error("[AdmobTools] e : " + e.Message + "\t cShapeFieldName : " + cShapeFieldName); + } + + return -1; + } + + + private static readonly string[] BannerStack = { "zza", "zzj", "zzi", "zze", "zza", "zzk", "zzae" }; + private static readonly string[] SpStack = { "zzb", "zzi", "zze", "zze", "zzae" }; + private static readonly string[] IvStack = { "zzc", "zzj", "zzf", "zzd", "zzae" }; + private static readonly string[] RvStack = { "zzb", "zzi", "zze", "zze", "zzae" }; + + + /// + /// 获取java ad view 对象 + /// + /// unity admob 实例化对象 + /// unity 引用 java 桥阶层的属性名 + /// java桥阶层,持有ad对象的方法名 + /// + private static AndroidJavaObject GetJavaAdViewOjb(object o, string cShapeFieldName, string javaFieldName) + { + if (o == null) + { + throw new NullReferenceException("adView is null ; " + cShapeFieldName + "\t " + javaFieldName); + } + + var type = o.GetType(); // 获取 BannerView 类型 + + var fieldInfo = type.GetField("_client", BindingFlags.NonPublic | BindingFlags.Instance); // 获取 _client 字段信息 + + if (fieldInfo == null) + { + throw new NullReferenceException("fieldInfo is null ; " + cShapeFieldName + "\t " + javaFieldName); + } + + var client = fieldInfo.GetValue(o); // 获取 _client 字段的值 + var clientType = client.GetType(); + var bannerViewFieldInfo = clientType.GetField(cShapeFieldName, BindingFlags.NonPublic | BindingFlags.Instance); + if (bannerViewFieldInfo == null) + { + throw new NullReferenceException("cShapeFieldName fieldInfo is null ; " + cShapeFieldName + "\t " + javaFieldName); + } + + var bannerViewAndroidJavaObject = (AndroidJavaObject)bannerViewFieldInfo.GetValue(client); + + var javaAdViewOjb = bannerViewAndroidJavaObject.Get(javaFieldName); + if (javaAdViewOjb == null) + { + throw new NullReferenceException("java obj is null ; " + cShapeFieldName + "\t " + javaFieldName); + } + + return javaAdViewOjb; + } + + /// + /// 获取 admob 的 AdValue 对象 + /// + /// admob 广告对象 + /// 内存位置 + /// AdValue 的对象 + private static AndroidJavaObject GetAdValue(AndroidJavaObject obj, string[] stack) + { + return stack.Aggregate(obj, (current, field) => + { + var androidJavaObject = current.Get(field); + if (androidJavaObject == null) + { + throw new NullReferenceException("androidJavaObject is null ; " + current + "\t " + field); + } + + return androidJavaObject; + }); + } + + /// + /// 获取 ecpm + /// + /// admob AdValue对象 + /// 广告收益 + private static double GetEcpm(AndroidJavaObject obj) + { + return obj.Get("zzd") * 1.0 / 1000000; + } + } +} \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs.meta new file mode 100644 index 0000000..0a6b527 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/Utils/AdmobUtils.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cc11ff1f480fa4d58969d2154bf532ec \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs index a9a7a86..2135a0b 100644 --- a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs +++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoAdsManager.cs @@ -3,8 +3,10 @@ using System.Collections; using System.Collections.Generic; using BigoAds.Scripts.Api; using Script.Common; +using Script.SDKManager.AdsSDKManager.Utils; using Script.Utils; using SDK.Utils; +using SDKManager.AdsSDKManager.Constant; using Unity.VisualScripting; using UnityEngine; @@ -20,36 +22,47 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager private List _rewardedAdUnits; public string bigo_app_id; + private bool _initialized; + public void Initialize() { + bigo_app_id = AdConfigParser.GetBigoAppId(); if (string.IsNullOrEmpty(bigo_app_id)) return; - _rewardedAdUnits = GetRewardedAdUnitsFromServer(); - _interstitialAdUnits = GetInterstitialAdUnitsFromServer(); + _rewardedAdUnits = AdConfigParser.GetBigoAdUnits(AdsType.Rewarded); + _interstitialAdUnits = AdConfigParser.GetBigoAdUnits(AdsType.Interstitial); BigoAdSdk.OnInitFinish += () => { - LoggerUtils.Debug($" bigo sdk init success"); - _rewardedAdManager = new BigoRewardedAdManager(); - _rewardedAdManager.InitializeAdUnits( - _rewardedAdUnits, - onAdLoaded: OnRewardedAdLoaded, - onAdLoadFailed: OnRewardedAdLoadFailed, - onAdShowed: OnRewardedAdShowed, - onAdDismissed: OnRewardedAdDismissed, - onAdError: OnRewardedAdError, - onAdClicked: OnRewardedAdClicked - ); - _interstitialAdManager = new BigoInterstitialAdManager(); - _interstitialAdManager.InitializeAdUnits( - _interstitialAdUnits, - onAdLoaded: OnInterstitialAdLoaded, - onAdLoadFailed: OnInterstitialAdLoadFailed, - onAdShowed: OnInterstitialAdShowed, - onAdDismissed: OnInterstitialAdDismissed, - onAdError: OnInterstitialAdError, - onAdClicked: OnInterstitialAdClicked + LoggerUtils.Debug($"[Bigo] sdk init success"); + if (_rewardedAdUnits.Count > 0) + { + _rewardedAdManager = new BigoRewardedAdManager(); + _rewardedAdManager.InitializeAdUnits( + _rewardedAdUnits, + onAdLoaded: OnRewardedAdLoaded, + onAdLoadFailed: OnRewardedAdLoadFailed, + onAdShowed: OnRewardedAdShowed, + onAdDismissed: OnRewardedAdDismissed, + onAdError: OnRewardedAdError, + onAdClicked: OnRewardedAdClicked ); + } + + if (_interstitialAdUnits.Count > 0) + { + _interstitialAdManager = new BigoInterstitialAdManager(); + _interstitialAdManager.InitializeAdUnits( + _interstitialAdUnits, + onAdLoaded: OnInterstitialAdLoaded, + onAdLoadFailed: OnInterstitialAdLoadFailed, + onAdShowed: OnInterstitialAdShowed, + onAdDismissed: OnInterstitialAdDismissed, + onAdError: OnInterstitialAdError, + onAdClicked: OnInterstitialAdClicked + ); + } + _initialized = true; }; - // todo + var config = new BigoAdConfig.Builder() .SetAppId(bigo_app_id) .SetDebugLog(false) @@ -57,7 +70,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager BigoAdSdk.Initialize(config); } - #region Rewarded + #region 激励广告功能 // 各个回调处理方法 private void OnRewardedAdLoaded(string adUnitId) { @@ -100,6 +113,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager public bool IsRewardedAvailable() { + if (!_initialized) return false; return _rewardedAdManager.GetAvailableAdUnits().Count > 0; } @@ -113,14 +127,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager return _rewardedAdManager.GetHighestPayingAdRevenue(); } - // 从服务器获取广告位配置 - private List GetRewardedAdUnitsFromServer() - { - // todo - return new List { "bigo_reward_unit_1", "bigo_reward_unit_2", "bigo_reward_unit_3" }; - } - - #region Interstitial + #region 插页广告功能 private void OnInterstitialAdLoaded(string adUnitId) { @@ -161,7 +168,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager public bool IsInterstitialAvailable() { - // 检查是否有任意一个广告位可用 + if (!_initialized) return false; return _interstitialAdManager.GetAvailableAdUnits().Count > 0; } @@ -185,8 +192,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager #endregion - #region 开屏广告 - + #region 开屏广告功能 public void LoadSplash() { } public bool IsSplashAvailable() { return false; } public void DisplaySplash() { } diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs index fa091ea..ef49a13 100644 --- a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs +++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoInterstitialAdManager.cs @@ -204,6 +204,5 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager _adRevenueCache.Clear(); } } - } diff --git a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs index e48f5d1..6024667 100644 --- a/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs +++ b/Assets/Script/SDKManager/AdsSDKManager/BigoAdsManager/BigoRewardedAdManager.cs @@ -21,12 +21,12 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager Action onAdDismissed = null, Action onAdError = null, Action onAdClicked = null) - { - foreach (var adUnitId in adUnitIds) { - CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError, onAdClicked); + foreach (var adUnitId in adUnitIds) + { + CreateRewardedAd(adUnitId, onAdLoaded, onAdLoadFailed, onAdShowed, onAdDismissed, onAdError, onAdClicked); + } } - } private void CreateRewardedAd(string adUnitId, Action onAdLoaded, Action onAdLoadFailed, @@ -37,7 +37,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager { if (_rewardedAds.ContainsKey(adUnitId)) { - Debug.LogWarning($"Ad unit {adUnitId} already exists"); + Debug.LogWarning($"[Bigo] Ad unit {adUnitId} already exists"); return; } @@ -50,7 +50,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager { _retryCounters[adUnitId] = 0; _adRevenueCache[adUnitId] = GetAdRevenue(rewardedAd); - LoggerUtils.Debug($"[BigoRewarded]-[Load]: {adUnitId} successfully"); + LoggerUtils.Debug($"[Bigo] Rewarded-[Load]: {adUnitId} successfully"); onAdLoaded?.Invoke(adUnitId); }; @@ -58,7 +58,7 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager { _retryCounters[adUnitId]++; double retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId])); - LoggerUtils.Debug($"[BigoRewarded]-[Load]: {adUnitId} failed, errorCode ={code}, error message = {msg}"); + LoggerUtils.Debug($"[Bigo] Rewarded-[Load]: {adUnitId} failed, errorCode ={code}, error message = {msg}"); // 延迟重试加载 _loadCallbacks[adUnitId] = () => LoadAd(adUnitId); @@ -68,19 +68,19 @@ namespace Script.SDKManager.AdsSDKManager.BigoAdsManager rewardedAd.OnAdShowed += (() => { - LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} show"); + LoggerUtils.Debug($"[Bigo] Rewarded-[interaction]: {adUnitId} show"); onAdShowed?.Invoke(adUnitId); }); rewardedAd.OnAdDismissed += (() => { - LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} dismiss"); + LoggerUtils.Debug($"[Bigo] Rewarded-[interaction]: {adUnitId} dismiss"); onAdDismissed?.Invoke(adUnitId); }); rewardedAd.OnAdError += ((code, msg) => { - LoggerUtils.Debug($"[BigoRewarded]-[interaction]: {adUnitId} ad error, errorCode ={code}, error message = {msg}"); + LoggerUtils.Debug($"[Bigo] Rewarded-[interaction]: {adUnitId} ad error, errorCode ={code}, error message = {msg}"); onAdError?.Invoke(adUnitId, code, msg); }); diff --git a/Assets/Script/SDKManager/AdsSDKManager/Constant.meta b/Assets/Script/SDKManager/AdsSDKManager/Constant.meta new file mode 100644 index 0000000..4bd3e75 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Constant.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7a4e52622bd8a4279a9d1621d28d3d23 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs b/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs new file mode 100644 index 0000000..06c3565 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs @@ -0,0 +1,16 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SDKManager.AdsSDKManager.Constant +{ + public enum AdsType + { + Interstitial, + Splash, + Rewarded, + Banner, + Native + } +} + diff --git a/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs.meta new file mode 100644 index 0000000..1e50856 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Constant/AdsType.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 1f8a13277f03d457ca5d5d19a6426b28 \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs b/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs new file mode 100644 index 0000000..cc56876 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs @@ -0,0 +1,13 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace SDKManager.AdsSDKManager.Constant +{ + public enum BannerAliignType + { + BannerCenterBottomAlign = 0, + BannerCenterTopAlign = 1, + } + +} diff --git a/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs.meta new file mode 100644 index 0000000..46ac1a0 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Constant/BannerAlignType.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: b8695a5a6cc14411892084d89818fdbe \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager.meta b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager.meta new file mode 100644 index 0000000..3f685a9 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 42f055653dec84aaa93cb4da11a99e99 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs new file mode 100644 index 0000000..0599209 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs @@ -0,0 +1,18 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class MaxAdsManager : MonoBehaviour +{ + // Start is called before the first frame update + void Start() + { + + } + + // Update is called once per frame + void Update() + { + + } +} diff --git a/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs.meta new file mode 100644 index 0000000..d04692b --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/MaxAdsManager/MaxAdsManager.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: cfac40dd2d010471d9cefd15bd2e7fcb \ No newline at end of file diff --git a/Assets/Script/SDKManager/AdsSDKManager/TpnAdsManager.meta b/Assets/Script/SDKManager/AdsSDKManager/TpnAdsManager.meta new file mode 100644 index 0000000..71fa314 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/TpnAdsManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 24456a37ebf404c6382cf98009e86446 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/Utils.meta b/Assets/Script/SDKManager/AdsSDKManager/Utils.meta new file mode 100644 index 0000000..8874621 --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Utils.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3a10db56e801646e3bd4dda28d8dfb74 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs b/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs new file mode 100644 index 0000000..bc02b5d --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs @@ -0,0 +1,243 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Script.Utils; +using SDKManager.AdsSDKManager.Constant; +using UnityEngine; + +namespace Script.SDKManager.AdsSDKManager.Utils +{ + public static class AdConfigParser + { + private static AdConfig _config; + public static AdConfig Parse(string json) + { + try + { + // 处理 JSON 字符串,确保它是有效的 + if (string.IsNullOrEmpty(json)) + { + LoggerUtils.Error("JSON string is null or empty"); + return null; + } + + // 使用 JsonUtility 解析 JSON + _config = JsonUtility.FromJson(json); + + if (_config == null) + { + LoggerUtils.Error("Failed to parse JSON to AdConfig"); + return null; + } + + LoggerUtils.Info("AdConfig parsed successfully"); + return _config; + } + catch (Exception e) + { + LoggerUtils.Error($"Error parsing AdConfig: {e.Message}"); + return null; + } + } + + /// + /// 获取 Admob 广告单元ID + /// + public static List GetAdmobAdUnits(AdsType adType) + { + if (_config == null) return new List(); + + return adType switch + { + AdsType.Interstitial => _config.admob_interstitial_units ?? new List(), + AdsType.Splash => _config.admob_splash_units ?? new List(), + AdsType.Rewarded => _config.admob_rewarded_units ?? new List(), + AdsType.Banner => _config.admob_banner_units ?? new List(), + AdsType.Native => _config.admob_native_units ?? new List(), + _ => new List() + }; + } + + /// + /// 获取 TopOn 广告单元ID + /// + public static List GetTopOnAdUnits(AdsType adType) + { + if (_config == null) return new List(); + + return adType switch + { + AdsType.Interstitial => _config.topon_interstitial_units ?? new List(), + AdsType.Splash => _config.topon_splash_units ?? new List(), + AdsType.Rewarded => _config.topon_rewarded_units ?? new List(), + AdsType.Banner => _config.topon_banner_units ?? new List(), + AdsType.Native => _config.topon_native_units ?? new List(), + _ => new List() + }; + } + + /// + /// 获取 AppLovin MAX 广告单元ID + /// + public static List GetMaxAdUnits(AdsType adType) + { + if (_config == null) return new List(); + + return adType switch + { + AdsType.Interstitial => _config.max_interstitial_units ?? new List(), + AdsType.Splash => _config.max_splash_units ?? new List(), + AdsType.Rewarded => _config.max_rewarded_units ?? new List(), + AdsType.Banner => _config.max_banner_units ?? new List(), + AdsType.Native => _config.max_native_units ?? new List(), + _ => new List() + }; + } + + /// + /// 获取 Bigo 广告单元ID + /// + public static List GetBigoAdUnits(AdsType adType) + { + if (_config == null) return new List(); + + return adType switch + { + AdsType.Interstitial => _config.bigo_i_inter_units ?? new List(), + AdsType.Rewarded => _config.bigo_i_reward_units ?? new List(), + _ => new List() + }; + } + + /// + /// 获取 Kwai 广告单元ID + /// + public static List GetKwaiAdUnits(AdsType adType) + { + if (_config == null) return new List(); + + return adType switch + { + AdsType.Interstitial => _config.kwai_i_inter_units ?? new List(), + AdsType.Rewarded => _config.kwai_i_reward_units ?? new List(), + _ => new List() + }; + } + + /// + /// 获取 TopOn App ID + /// + public static string GetTopOnAppId() + { + return _config?.topon_app_id; + } + + /// + /// 获取 TopOn App Key + /// + public static string GetTopOnAppKey() + { + return _config?.topon_app_key; + } + + /// + /// 获取 AppLovin MAX App Key + /// + public static string GetMaxAppKey() + { + return _config?.max_app_key; + } + + /// + /// 获取 Bigo App ID + /// + public static string GetBigoAppId() + { + return _config?.bigo_app_id; + } + + /// + /// 获取 Kwai App ID + /// + public static string GetKwaiAppId() + { + return _config?.kwai_app_id; + } + + /// + /// 获取 Kwai App Token + /// + public static string GetKwaiAppToken() + { + return _config?.kwai_app_token; + } + + /// + /// 获取广告过期时间(秒) + /// + public static int GetAdExpireInSec() + { + return _config?.ad_expire_in_sec ?? 3000; // 默认值 + } + + /// + /// 检查配置是否已加载 + /// + public static bool IsConfigLoaded() + { + return _config != null; + } + + /// + /// 清空已加载的配置 + /// + public static void ClearConfig() + { + _config = null; + } + } + + [Serializable] + public class AdConfig + { + // Admob 配置 + public List admob_interstitial_units; + public List admob_splash_units; + public List admob_rewarded_units; + public List admob_banner_units; + public List admob_native_units; + + // TopOn 配置 + public string topon_app_id; + public string topon_app_key; + public List topon_interstitial_units; + public List topon_splash_units; + public List topon_rewarded_units; + public List topon_banner_units; + public List topon_native_units; + + // AppLovin MAX 配置 + public string max_app_key; + public List max_interstitial_units; + public List max_splash_units; + public List max_rewarded_units; + public List max_banner_units; + public List max_native_units; + + // Bigo 配置 + public string bigo_app_id; + public List bigo_i_inter_units; + public List bigo_i_reward_units; + + // Kwai 配置 + public string kwai_app_id; + public string kwai_app_token; + public List kwai_i_inter_units; + public List kwai_i_reward_units; + + // 通用配置 + public int ad_expire_in_sec; + } + + } + diff --git a/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs.meta b/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs.meta new file mode 100644 index 0000000..09e555a --- /dev/null +++ b/Assets/Script/SDKManager/AdsSDKManager/Utils/AdConfigParser.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: c1122fdef681d4e25898cbff43f3cff7 \ No newline at end of file diff --git a/Assets/ThinkupTpnPlugin.meta b/Assets/ThinkupTpnPlugin.meta new file mode 100644 index 0000000..5d80ed4 --- /dev/null +++ b/Assets/ThinkupTpnPlugin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3aa9f15a8be214473a23e5ee0d0388cd +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds.meta new file mode 100644 index 0000000..de8d8fc --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bf4357cd1449f42b7a8c7335ed7a1631 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins.meta new file mode 100644 index 0000000..187f4ac --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9a463baac9e384e99ae8f85dca7666df +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android.meta new file mode 100644 index 0000000..5679c8f --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 371f62d9f050f42d09789990d2b3dbbc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina.meta new file mode 100644 index 0000000..5cbeceb --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4e5a003d5a8e14790aff92e9a883b57d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation.meta new file mode 100644 index 0000000..f1cf63f --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 219ad8594ee44474c99234d8768f44d0 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/admob.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/admob.meta new file mode 100644 index 0000000..b9d7a8c --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/admob.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b62202c39d50040578cd9b1b8fb8403f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/applovin.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/applovin.meta new file mode 100644 index 0000000..69a6898 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/applovin.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a9871c8fe44b4219bd38f0a029a6221 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/bigo.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/bigo.meta new file mode 100644 index 0000000..dcd1bf9 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/bigo.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 148734b55ad8349448d3b8ac80620373 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/fyber.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/fyber.meta new file mode 100644 index 0000000..7129a2a --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/fyber.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a1a74d89005b426d905e779eb0972e9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm.meta new file mode 100644 index 0000000..986cac6 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/gtm.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b09bfd714a0a94df2a20ba0d19e1496a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai.meta new file mode 100644 index 0000000..37b4875 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/kwai.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1181a6a98099c43ff904e5d2abf5bbff +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle.meta new file mode 100644 index 0000000..d24812a --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/pangle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eeb6f5b37f49c41b0b3d1f98d657d708 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/unityads.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/unityads.meta new file mode 100644 index 0000000..5f9a055 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/unityads.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4bffbbec5c99440799f476ed4c8eeeec +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle.meta new file mode 100644 index 0000000..db6b8ca --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/mediation/vungle.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d1deff81eb8d847ad8f79c0910672b87 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/thinkup_base.meta b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/thinkup_base.meta new file mode 100644 index 0000000..0d64d90 --- /dev/null +++ b/Assets/ThinkupTpnPlugin/AnyThinkAds/Plugins/Android/NonChina/thinkup_base.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5011df97def874ed5b553d91a4cc6133 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: