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

443 lines
17 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using EFSDK;
using GoogleMobileAds.Api;
using UnityEngine;
namespace WZ
{
class ShowNativePosition
{
public NativeOverlayAd NativeOverlayAd;
public NativeAdPosition Position;
public ShowNativePosition(NativeOverlayAd nativeOverlayAd, NativeAdPosition position)
{
NativeOverlayAd = nativeOverlayAd;
Position = position;
}
}
public class AdmobNativeAdManager
{
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>();
private Dictionary<string, float> _adStartLoadTimes = new Dictionary<string, float>();
private Dictionary<string, ShowNativePosition> showingNativeAds = new();
public void InitializeAdUnits(List<string> adUnitIds)
{
foreach (var adUnitId in adUnitIds)
{
CreateNativeAd(adUnitId);
}
}
private void CreateNativeAd(string adUnitId)
{
if (string.IsNullOrEmpty(adUnitId)) return;
if (_nativeAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} already exists");
return;
}
LoadAd(adUnitId);
_adRevenueCache[adUnitId] = 0;
}
public void LoadAd(string adUnitId, bool timingRefresh = false)
{
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} load start , timingRefresh {timingRefresh}");
//判断在线参数是否包含这个id
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
NativeOverlayAd.Load(adUnitId, new AdRequest(), new NativeAdOptions(), (NativeOverlayAd ad, LoadAdError error) =>
{
_adStartLoadTimes[adUnitId] = Time.realtimeSinceStartup;
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId} load end, timingRefresh {timingRefresh}. {ad} error {error}");
if (error != null || ad == null)
{
if (!timingRefresh)
{
if (!_retryCounters.TryAdd(adUnitId, 0))
{
_retryCounters[adUnitId]++;
}
}
var adSource = "";
if (ad != null)
{
adSource = ad.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "";
}
var reason = "";
if (error != null)
{
reason = error.GetMessage();
}
AdsActionEvents.TrackAdFailToLoad(PlatformType.Admob,
adSource,
adUnitId,
AdsType.Native,
Time.realtimeSinceStartup - _adStartLoadTimes[adUnitId],
reason);
// 定时任务的刷新,由定时任务自己去刷新
if (timingRefresh)
{
if (!showingNativeAds.ContainsKey(adUnitId))
{
LoggerUtils.Debug($"[Admob] Native Ad unit {adUnitId}, 已经隐藏了失败了也不需要在重新load了");
return;
}
TimingRefresh(adUnitId);
return;
}
var retryDelay = Math.Pow(2, Math.Min(6, _retryCounters[adUnitId]));
TimerUtils.Instance.DelayExecute((float)retryDelay, () => { LoadAd(adUnitId); });
LoggerUtils.Error($"[Admob] Native Ad unit {adUnitId}, timingRefresh {timingRefresh} ad failed to load an ad with error : " + error + " \n retryDelay :" + retryDelay);
return;
}
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
AdsActionEvents.TrackAdLoaded(PlatformType.Admob,
ad?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "",
adUnitId,
AdsType.Native,
Time.realtimeSinceStartup - _adStartLoadTimes[adUnitId]);
_retryCounters[adUnitId] = 0;
// 临时缓存上一次的native ad以便于刷新的时候显示了新的隐藏老的。
var tempAd = _nativeAds.GetValueOrDefault(adUnitId, null);
var nativeEcpm = AdmobUtils.GetNativeEcpm(ad);
_nativeAds[adUnitId] = ad;
_adRevenueCache[adUnitId] = nativeEcpm;
LoggerUtils.Debug($"Admob Native ad loaded with, timingRefresh {timingRefresh} nativeEcpm = {nativeEcpm} response : " + ad.GetResponseInfo().ToString());
AdsKeyEvents.Instance.LogAdFPUEvents(AdsType.Native);
ad.OnAdPaid += (AdValue adValue) =>
{
LoggerUtils.Debug($"[Admob] Native ad paid {adValue.Value} {adValue.CurrencyCode}.");
AdmobAdsManager.Instance.TrackAdImpression(ad?.GetResponseInfo()?.GetLoadedAdapterResponseInfo().AdSourceName??"",
ad?.GetResponseInfo()?.GetLoadedAdapterResponseInfo().AdSourceInstanceId??"",
adValue,
AdsType.Native,
adUnitId);
};
ad.OnAdImpressionRecorded += () => { LoggerUtils.Debug("[Admob] Native ad recorded an impression."); };
ad.OnAdClicked += () =>
{
AdsActionEvents.TrackAdClicked(PlatformType.Admob,
ad?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "",
adUnitId,
AdsType.Native,
"",
AdmobUtils.GetNativeEcpm(ad));
LoggerUtils.Debug("[Admob] Native ad was clicked.");
};
ad.OnAdFullScreenContentOpened += () => { LoggerUtils.Debug("[Admob] Native ad full screen content opened."); };
ad.OnAdFullScreenContentClosed += () =>
{
AdsActionEvents.TrackAdClicked(PlatformType.Admob,
ad?.GetResponseInfo()?.GetLoadedAdapterResponseInfo()?.AdSourceName ?? "",
adUnitId,
AdsType.Native,
"",
AdmobUtils.GetNativeEcpm(ad));
LoggerUtils.Debug("[Admob] Native ad full screen content closed.");
};
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");
}
LoggerUtils.Warning("[Admob] Native ad timing refresh , show ad");
ShowAd(showing.Position, adUnitId, tempAd, showingNativeOverlayAd);
}
else
{
LoggerUtils.Warning($"[Admob] Native ad timing refresh , show fail , showing native ads not ad unit id , {adUnitId} , 广告已经隐藏了,刷新成功,不需要再去显示出来");
}
}
});
}
// 显示价格最高的广告
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)
{
if (!AdmobAdsManager.Instance.FindAdsID(AdsType.Native, adUnitId))
{
return;
}
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);
var showNativePosition = showingNativeAds.GetValueOrDefault(adUnitId, null);
var lastAdResponseId = lastAd?.GetResponseInfo()?.GetResponseId();
var lastShowAdResponseId = lastShowAd?.GetResponseInfo()?.GetResponseId();
var lastShowAdResponseId2 = showNativePosition?.NativeOverlayAd?.GetResponseInfo()?.GetResponseId();
var showAdResponseId = ad.GetResponseInfo()?.GetResponseId();
LoggerUtils.Debug(
$"[Admob] Native ad ShowAd [showingNativeAds] {adUnitId} , showAdResponseId = {showAdResponseId} , lastAdResponseId = {lastAdResponseId} , lastShowAdResponseId = {lastShowAdResponseId} , lastShowAdResponseId2 = {lastShowAdResponseId2}");
showingNativeAds[adUnitId] = new ShowNativePosition(ad, position);
ad.Show();
try
{
lastAd?.Hide();
lastShowAd?.Hide();
showNativePosition?.NativeOverlayAd?.Hide();
}
catch (Exception e)
{
LoggerUtils.Error($"[Admob] Native ad Hide fail {adUnitId} , e : {e.Message}");
}
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;
}
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);
}
private float GetLoadedTime(string adUnitId)
{
return _adStartLoadTimes.TryGetValue(adUnitId, out var time) ? time : 0;
}
// 检查特定广告位是否可用
public bool IsAdAvailable(string adUnitId)
{
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 double GetAdRevenue(string adUnit)
{
if (!string.IsNullOrEmpty(adUnit) &&
_adRevenueCache.TryGetValue(adUnit, out var revenue))
{
return revenue;
}
return -1;
}
// 清理资源
public void Destroy()
{
foreach (var ad in _nativeAds.Values)
{
ad.Destroy();
}
_nativeAds.Clear();
_adRevenueCache.Clear();
}
public IEnumerator RemoveNative(string adUnitId)
{
// 不需要等待了
// yield return new WaitForSeconds(0.2f);
if (adUnitId == null || string.IsNullOrEmpty(adUnitId))
{
foreach (var key in showingNativeAds.Keys.ToList())
{
var ad = showingNativeAds[key].NativeOverlayAd;
LoggerUtils.Debug($"[Admob] Native ad removing [showingNativeAds] {adUnitId} , ad {ad.GetResponseInfo()?.GetResponseId()}");
ad.Hide();
// 从字典中删除元素
showingNativeAds.Remove(key);
LoadAd(key);
}
yield break;
}
if (showingNativeAds.TryGetValue(adUnitId, out var tempAd))
{
var ad = tempAd.NativeOverlayAd;
LoggerUtils.Debug($"[Admob] Native ad removing [showingNativeAds] {adUnitId} , ad {ad.GetResponseInfo()?.GetResponseId()}");
ad.Hide();
showingNativeAds.Remove(adUnitId);
LoadAd(adUnitId);
}
else
{
LoggerUtils.Debug($"[Admob] Native ad removing NativeAd {adUnitId} , failed to remove NativeAd");
}
}
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);
}
}
}
}