SDK_UnityMoney/Assets/Script/SDKManager/AdsSDKManager/AdmobAdsManager/AdmobNativeAdManager.cs

441 lines
17 KiB
C#
Raw Normal View History

2025-09-01 15:57:10 +00:00
using System;
using System.Collections;
using System.Collections.Generic;
2025-09-01 15:57:10 +00:00
using System.Linq;
2025-09-15 15:12:13 +00:00
using EFSDK;
2025-09-01 15:57:10 +00:00
using GoogleMobileAds.Api;
using UnityEngine;
2025-09-01 10:32:50 +00:00
namespace WZ
2025-09-01 15:57:10 +00:00
{
2025-09-15 15:12:13 +00:00
class ShowNativePosition
{
public NativeOverlayAd NativeOverlayAd;
public NativeAdPosition Position;
public ShowNativePosition(NativeOverlayAd nativeOverlayAd, NativeAdPosition position)
{
NativeOverlayAd = nativeOverlayAd;
Position = position;
}
}
2025-09-01 15:57:10 +00:00
public class AdmobNativeAdManager
{
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>();
2025-09-03 08:56:30 +00:00
private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>();
2025-09-15 15:12:13 +00:00
private Dictionary<string, ShowNativePosition> showingNativeAds = new();
2025-09-03 05:42:30 +00:00
2025-09-01 15:57:10 +00:00
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
{
if (string.IsNullOrEmpty(adUnitId)) return;
2025-09-01 15:57:10 +00:00
if (_nativeAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} already exists");
return;
}
2025-09-01 15:57:10 +00:00
LoadAd(adUnitId);
_adRevenueCache[adUnitId] = 0;
2025-08-31 13:19:46 +00:00
}
2025-09-15 15:12:13 +00:00
public void LoadAd(string adUnitId, bool timingRefresh = false)
2025-08-31 13:19:46 +00:00
{
2025-09-15 15:12:13 +00:00
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} load start , timingRefresh {timingRefresh}");
//判断在线参数是否包含这个id
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
2025-09-01 15:57:10 +00:00
NativeOverlayAd.Load(adUnitId, new AdRequest(), new NativeAdOptions(), (NativeOverlayAd ad, LoadAdError error) =>
{
2025-09-03 05:42:30 +00:00
_adStartLoadTimes[adUnitId] = Time.realtimeSinceStartup;
2025-09-15 15:12:13 +00:00
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} load end, timingRefresh {timingRefresh}. {ad} error {error}");
2025-09-01 15:57:10 +00:00
if (error != null || ad == null)
{
2025-09-17 10:42:58 +00:00
if (!timingRefresh)
2025-09-02 02:07:10 +00:00
{
2025-09-17 10:42:58 +00:00
if (!_retryCounters.TryAdd(adUnitId, 0))
{
_retryCounters[adUnitId]++;
}
2025-09-02 02:07:10 +00:00
}
2025-09-03 08:56:30 +00:00
2025-09-17 10:42:58 +00:00
2025-09-03 08:56:30 +00:00
var adSource = "";
if (ad != null)
{
adSource = ad.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName;
}
var reason = "";
if (error != null)
{
reason = error.GetMessage();
}
2025-09-03 05:42:30 +00:00
AdsActionEvents.TrackAdFailToLoad(PlatformType.Admob,
2025-09-03 08:56:30 +00:00
adSource,
2025-09-03 05:42:30 +00:00
adUnitId,
AdsType.Native,
2025-09-04 09:19:05 +00:00
Time.realtimeSinceStartup - _adStartLoadTimes[adUnitId],
reason);
2025-09-03 08:56:30 +00:00
2025-09-17 10:42:58 +00:00
// 定时任务的刷新,由定时任务自己去刷新
if (timingRefresh)
{
if (!showingNativeAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId}, 已经隐藏了失败了也不需要在重新load了");
return;
}
TimingRefresh(adUnitId);
return;
}
2025-09-01 15:57:10 +00:00
var retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId]));
2025-09-17 10:42:58 +00:00
TimerUtils.Instance.DelayExecute((float)retryDelay, () => { LoadAd(adUnitId); });
2025-09-15 15:12:13 +00:00
LoggerUtils.Error($"[Admob] Native Ad unit {adUnitId}, timingRefresh {timingRefresh} ad failed to load an ad with error : " + error + " \n retryDelay :" + retryDelay);
2025-09-01 15:57:10 +00:00
return;
}
2025-09-15 07:55:38 +00:00
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
2025-09-03 08:56:30 +00:00
2025-09-03 05:42:30 +00:00
AdsActionEvents.TrackAdLoaded(PlatformType.Admob,
ad.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Native,
Time.realtimeSinceStartup - _adStartLoadTimes[adUnitId]);
2025-09-01 15:57:10 +00:00
_retryCounters[adUnitId] = 0;
2025-09-15 15:12:13 +00:00
// 临时缓存上一次的native ad以便于刷新的时候显示了新的隐藏老的。
var tempAd = _nativeAds.GetValueOrDefault(adUnitId, null);
2025-09-02 08:22:20 +00:00
var nativeEcpm = AdmobUtils.GetNativeEcpm(ad);
2025-09-01 15:57:10 +00:00
_nativeAds[adUnitId] = ad;
2025-09-02 08:22:20 +00:00
_adRevenueCache[adUnitId] = nativeEcpm;
2025-09-15 15:12:13 +00:00
LoggerUtils.Debug($"Admob Native ad loaded with, timingRefresh {timingRefresh} nativeEcpm = {nativeEcpm} response : " + ad.GetResponseInfo().ToString());
2025-09-01 15:57:10 +00:00
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,
2025-09-02 13:42:07 +00:00
adUnitId);
2025-09-01 15:57:10 +00:00
};
ad.OnAdImpressionRecorded += () => { LoggerUtils.Debug("[Admob] Native ad recorded an impression."); };
2025-09-03 05:42:30 +00:00
ad.OnAdClicked += () =>
{
AdsActionEvents.TrackAdClicked(PlatformType.Admob,
ad.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Native,
"",
AdmobUtils.GetNativeEcpm(ad));
LoggerUtils.Debug("[Admob] Native ad was clicked.");
};
2025-09-01 15:57:10 +00:00
ad.OnAdFullScreenContentOpened += () => { LoggerUtils.Debug("[Admob] Native ad full screen content opened."); };
2025-09-03 08:56:30 +00:00
ad.OnAdFullScreenContentClosed += () =>
{
2025-09-03 05:42:30 +00:00
AdsActionEvents.TrackAdClicked(PlatformType.Admob,
ad.GetResponseInfo().GetLoadedAdapterResponseInfo().AdSourceName,
adUnitId,
AdsType.Native,
"",
AdmobUtils.GetNativeEcpm(ad));
2025-09-03 08:56:30 +00:00
LoggerUtils.Debug("[Admob] Native ad full screen content closed.");
};
2025-09-15 15:12:13 +00:00
if (timingRefresh && tempAd != null)
{
if (showingNativeAds.TryGetValue(adUnitId, out var showing))
{
var showingNativeOverlayAd = showing.NativeOverlayAd;
if (showingNativeOverlayAd != tempAd)
{
LoggerUtils.Error("[Admob] Native ad Error!!!! showing.NativeOverlayAd != tempAd");
}
2025-09-15 15:12:13 +00:00
LoggerUtils.Warning("[Admob] Native ad timing refresh , show ad");
ShowAd(showing.Position, adUnitId, tempAd, showingNativeOverlayAd);
2025-09-15 15:12:13 +00:00
}
else
{
2025-09-17 10:42:58 +00:00
LoggerUtils.Warning($"[Admob] Native ad timing refresh , show fail , showing native ads not ad unit id , {adUnitId} , 广告已经隐藏了,刷新成功,不需要再去显示出来");
2025-09-15 15:12:13 +00:00
}
}
2025-09-01 15:57:10 +00:00
});
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, NativeOverlayAd lastAd = null, NativeOverlayAd lastShowAd = null)
2025-09-01 15:57:10 +00:00
{
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
2025-09-15 07:55:38 +00:00
2025-09-01 15:57:10 +00:00
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);
2025-09-18 09:37:37 +00:00
var showNativePosition = showingNativeAds[adUnitId];
var lastAdResponseId = lastAd?.GetResponseInfo()?.GetResponseId();
var lastShowAdResponseId = lastShowAd?.GetResponseInfo()?.GetResponseId();
var lastShowAdResponseId2 = showNativePosition?.NativeOverlayAd?.GetResponseInfo()?.GetResponseId();
var showAdResponseId = ad.GetResponseInfo()?.GetResponseId();
LoggerUtils.Debug(
2025-09-18 09:40:33 +00:00
$"[Admob] Native ad ShowAd [showingNativeAds] {adUnitId} , showAdResponseId = {showAdResponseId} , lastAdResponseId = {lastAdResponseId} , lastShowAdResponseId = {lastShowAdResponseId} , lastShowAdResponseId2 = {lastShowAdResponseId2}");
2025-09-18 09:37:37 +00:00
2025-09-15 15:12:13 +00:00
showingNativeAds[adUnitId] = new ShowNativePosition(ad, position);
2025-09-01 15:57:10 +00:00
ad.Show();
2025-09-18 09:37:37 +00:00
try
{
lastAd?.Hide();
lastShowAd?.Hide();
showNativePosition?.NativeOverlayAd?.Hide();
}
catch (Exception e)
{
LoggerUtils.Error($"[Admob] Native ad Hide fail {adUnitId} , e : {e.Message}");
}
2025-09-15 15:12:13 +00:00
TimingRefresh(adUnitId);
}
}
private void TimingRefresh(string adUnitId)
{
var nativeReflashGap = int.Parse(FireBaseRemoteConfigManager.Instance.GetRemoteConfigString("Native_Reflash_Gap", "0"));
if (nativeReflashGap <= 0)
{
LoggerUtils.Debug($"[Admob] Native ad ({adUnitId}) timing refresh failed. nativeReflashGap = 0");
return;
}
if (adUnitId == StaticValue.AdmobFullNativeId)
{
LoggerUtils.Debug($"[Admob] Native ad ({adUnitId}) timing refresh finished. ad unit id is full native id.");
return;
}
if (!showingNativeAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] Native ad ({adUnitId}) timing refresh finished. ad unit is not show.");
return;
2025-09-01 15:57:10 +00:00
}
2025-09-15 15:12:13 +00:00
WLoom.QueueOnMainThread(o =>
{
var refreshAdUnitId = (string)o;
LoggerUtils.Debug($"[Admob] Native ad ({adUnitId}) timing refresh load start refreshAdUnitId : {refreshAdUnitId}.");
if (showingNativeAds.ContainsKey(refreshAdUnitId))
{
LoadAd(refreshAdUnitId, true);
}
else
{
LoggerUtils.Warning($"[Admob] Native ad ({adUnitId}) timing refresh finished. ad unit is not show. refreshAdUnitId : {refreshAdUnitId}.");
}
}, adUnitId, nativeReflashGap);
2025-09-01 15:57:10 +00:00
}
2025-09-03 05:42:30 +00:00
private float GetLoadedTime(string adUnitId)
2025-09-03 08:56:30 +00:00
{
return _adStartLoadTimes.TryGetValue(adUnitId, out var time) ? time : 0;
2025-09-03 05:42:30 +00:00
}
2025-09-03 08:56:30 +00:00
2025-09-01 15:57:10 +00:00
// 检查特定广告位是否可用
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;
}
2025-09-15 07:55:38 +00:00
// 获取广告收益信息
public double GetAdRevenue(string adUnit)
{
if (!string.IsNullOrEmpty(adUnit) &&
_adRevenueCache.TryGetValue(adUnit, out var revenue))
{
return revenue;
}
return -1;
}
2025-09-15 07:55:38 +00:00
2025-09-01 15:57:10 +00:00
// 清理资源
public void Destroy()
{
foreach (var ad in _nativeAds.Values)
{
ad.Destroy();
}
_nativeAds.Clear();
_adRevenueCache.Clear();
}
public IEnumerator RemoveNative(string adUnitId)
2025-09-01 15:57:10 +00:00
{
2025-09-15 07:55:38 +00:00
// 不需要等待了
// yield return new WaitForSeconds(0.2f);
2025-09-01 15:57:10 +00:00
if (adUnitId == null || string.IsNullOrEmpty(adUnitId))
{
2025-09-15 15:12:13 +00:00
foreach (var key in showingNativeAds.Keys.ToList())
2025-09-01 15:57:10 +00:00
{
2025-09-18 09:37:37 +00:00
var ad = showingNativeAds[key].NativeOverlayAd;
LoggerUtils.Debug($"[Admob] Native ad removing [showingNativeAds] {adUnitId} , ad {ad.GetResponseInfo()?.GetResponseId()}");
ad.Hide();
2025-09-15 15:12:13 +00:00
// 从字典中删除元素
showingNativeAds.Remove(key);
LoadAd(key);
2025-09-01 15:57:10 +00:00
}
yield break;
2025-09-01 15:57:10 +00:00
}
2025-09-15 07:55:38 +00:00
if (showingNativeAds.TryGetValue(adUnitId, out var tempAd))
2025-09-01 15:57:10 +00:00
{
2025-09-18 09:37:37 +00:00
var ad = tempAd.NativeOverlayAd;
LoggerUtils.Debug($"[Admob] Native ad removing [showingNativeAds] {adUnitId} , ad {ad.GetResponseInfo()?.GetResponseId()}");
ad.Hide();
2025-09-15 07:55:38 +00:00
showingNativeAds.Remove(adUnitId);
2025-09-02 08:24:38 +00:00
LoadAd(adUnitId);
2025-09-01 15:57:10 +00:00
}
2025-09-15 07:55:38 +00:00
else
{
LoggerUtils.Debug($"[Admob] Native ad removing NativeAd {adUnitId} , failed to remove NativeAd");
}
2025-09-01 15:57:10 +00:00
}
2025-09-15 07:55:38 +00:00
public void ClearAds(string[] adUnitIds)
{
// 将数组转换为HashSet以提高查找性能
HashSet<string> validKeys = new HashSet<string>(adUnitIds);
// 收集需要移除的key
List<string> keysToRemove = new List<string>();
foreach (var key in _nativeAds.Keys)
{
if (!validKeys.Contains(key))
{
keysToRemove.Add(key);
}
}
// 移除不在数组中的key
foreach (string key in keysToRemove)
{
_nativeAds.Remove(key);
_retryCounters.Remove(key);
_adStartLoadTimes.Remove(key);
_adRevenueCache.Remove(key);
}
}
2025-09-01 15:57:10 +00:00
}
}