com.guru.unity.sdk.core/Runtime/GuruCore/Runtime/Ads/ADServiceBase.cs

615 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using System;
using Guru;
using UnityEngine;
namespace Guru
{
public abstract class ADServiceBase<T> : IADService where T : new()
{
// 单利定义
private static T _instance;
public static T Instance
{
get
{
if (null == _instance) _instance = new T();
return _instance;
}
}
protected static readonly string Tag = "[Ads]";
public bool IsInitialized => MaxSdk.IsInitialized() || _isServiceStarted;
protected bool IsNetworkEnabled => Application.internetReachability != NetworkReachability.NotReachable;
private bool _isServiceStarted;
protected bool _isDebugMode;
protected bool _isAutoLoadAds;
private Action _onSdkInitReady;
public static Action OnBannerLoaded;
public static Action OnInterstitialLoaded;
public static Action OnInterstitialFailed;
public static Action OnRewardLoaded;
public static Action OnRewardFailed;
private AdsModel _model;
/// <summary>
/// 启动广告服务
/// </summary>
/// <param name="callback">广告初始化回调</param>
/// <param name="autoLoadAds">自动启动广告加载</param>
/// <param name="isDebugMode">debug模式</param>
public virtual void StartService(Action callback = null, bool autoLoadAds = true, bool isDebugMode = false)
{
if (IsInitialized) return; // 已经初始化后, 无需再次初始化
_isServiceStarted = true;
_isAutoLoadAds = autoLoadAds;
_isDebugMode = isDebugMode;
_onSdkInitReady = callback;
_model = AdsModel.Create();
this.Log("AD SDK Start Init");
//-------------- 初始化回调 ------------------
MaxSdkCallbacks.OnSdkInitializedEvent += OnMaxSdkInitializedCallBack;
MaxSdkCallbacks.Interstitial.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.Rewarded.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.Banner.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
MaxSdkCallbacks.MRec.OnAdRevenuePaidEvent += OnAdRevenuePaidEvent;
//--------------- Banner 回调 -----------------
MaxSdkCallbacks.Banner.OnAdLoadedEvent += OnBannerLoadedEvent;
MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += OnBannerFailedEvent;
MaxSdkCallbacks.Banner.OnAdClickedEvent += OnBannerClickedEvent;
//--------------- IV 回调 -----------------
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += OnInterstitialLoadedEvent;
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += OnInterstitialFailedEvent;
MaxSdkCallbacks.Interstitial.OnAdDisplayFailedEvent += InterstitialFailedToDisplayEvent;
MaxSdkCallbacks.Interstitial.OnAdClickedEvent += OnInterstitialClickEvent;
MaxSdkCallbacks.Interstitial.OnAdDisplayedEvent += OnInterstitialDisplayEvent;
MaxSdkCallbacks.Interstitial.OnAdHiddenEvent += OnInterstitialDismissedEvent;
//--------------- RV 回调 -----------------
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += OnRewardedAdLoadedEvent;
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += OnRewardedAdFailedEvent;
MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += OnRewardedAdFailedToDisplayEvent;
MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent += OnRewardedAdDisplayedEvent;
MaxSdkCallbacks.Rewarded.OnAdClickedEvent += OnRewardedAdClickedEvent;
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += OnRewardedAdDismissedEvent;
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedAdReceivedRewardEvent;
//-------------- SDK 初始化 -------------------
MaxSdk.SetVerboseLogging(_isDebugMode);
InitService();
}
protected virtual void InitService()
{
}
private void OnMaxSdkInitializedCallBack(MaxSdkBase.SdkConfiguration sdkConfiguration)
{
this.Log("AD SDK Init Success");
if (_isAutoLoadAds) OnMaxSdkReady();
_onSdkInitReady?.Invoke();
}
protected virtual void OnMaxSdkReady()
{
//TODO:各个项目根据自己情况进行修改模版默认做法是SDK初始化完成后就进行广告请求
RequestBannerAD();
RequestInterstitialAD();
RequestRewardedAD();
}
/// <summary>
/// 可加载广告
/// </summary>
/// <returns></returns>
public virtual bool CanLoadAds()
{
return IsInitialized && IsNetworkEnabled;
}
#region ILRD
private double TchAD001RevValue
{
get => _model.TchAD001RevValue;
set => _model.TchAD001RevValue = value;
}
private double TchAD02RevValue
{
get => _model.TchAD02RevValue;
set => _model.TchAD02RevValue = value;
}
public void OnAdRevenuePaidEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
if (adInfo == null) return;
// #1. ad_impression
OnAdImpression(adInfo);
// #2. tch_ad_rev_roas calculation
double revenue = adInfo.Revenue;
CalcTaichi001Value(revenue);
CalcTaichi02Value(revenue);
// #3. Adjust ad_revenue
AdjustService.TrackADRevenue(adInfo);
}
/// <summary>
/// 广告ARO收益打点
/// </summary>
/// <param name="adInfo"></param>
private void OnAdImpression(MaxSdkBase.AdInfo adInfo)
{
Analytics.ADImpression(adInfo);
}
/// <summary>
/// 计算太极001收益
/// </summary>
/// <param name="revenue"></param>
private void CalcTaichi001Value(double revenue)
{
TchAD001RevValue += revenue;
double revenueValue = TchAD001RevValue;
Debug.Log($"[TaichConfig] get <TchAD001RevValue> totally: {revenueValue}");
if (revenueValue >= Analytics.Tch001TargetValue)
{
Debug.Log($"[TaichConfig] call <tch_ad_rev_roas_001> with value: {revenueValue}");
Analytics.Tch001ADRev(revenueValue);
TchAD001RevValue = 0.0;
}
}
/// <summary>
/// 计算太极02收益
/// </summary>
/// <param name="revenue"></param>
private void CalcTaichi02Value(double revenue)
{
if (!Analytics.EnableTch02Event) return;
TchAD02RevValue += revenue;
double revenueValue = TchAD02RevValue;
Debug.Log($"[Ads] get <TchAD02RevValue> totally: {revenueValue}");
if (revenueValue >= Analytics.Tch02TargetValue)
{
Debug.Log($"[Ads] call <tch_ad_rev_roas_02> with value: {revenueValue}");
Analytics.Tch02ADRev(revenueValue);
TchAD02RevValue = 0.0;
}
}
#endregion
#region Banner Ads
private string _backColorStr = "#50A436";
private Color _backColor = new Color(0, 0, 0, 0);
private string _badsCategory;
protected float _badsloadStartTime = 0;
private int GetAdsLoadDuration(ref float startTime)
{
int duration = (int)((Time.realtimeSinceStartup - startTime) * 1000);
startTime = 0;
return duration;
}
public virtual void RequestBannerAD()
{
LoadMaxBannerAd();
}
/// <summary>
/// Banner MAX 加载方式
/// </summary>
protected void LoadMaxBannerAd()
{
OnLoadBads();
// Banners are automatically sized to 320x50 on phones and 728x90 on tablets
// You may use the utility method `MaxSdkUtils.isTablet()` to help with view sizing adjustments
var id = GetBannerID();
MaxSdk.CreateBanner(id, MaxSdkBase.BannerPosition.BottomCenter);
MaxSdk.SetBannerExtraParameter(id, "adaptive_banner", "false");
// Set background or background color for banners to be fully functional
MaxSdk.SetBannerBackgroundColor(id, _backColor);
// Analytics.ADBadsLoad(GetBannerID());
Analytics.ADBadsLoad(AdParams.Build(id));
}
public void OnLoadBads()
{
_badsloadStartTime = Time.realtimeSinceStartup;
}
public virtual void ShowBanner(string category = "")
{
_badsCategory = category;
string adUnitId = GetBannerID();
MaxSdk.ShowBanner(adUnitId);
MaxSdk.SetBannerBackgroundColor(adUnitId, _backColor);
OnBannerImpEvent(adUnitId);
}
public virtual void HideBanner()
{
MaxSdk.HideBanner(GetBannerID());
}
private void OnBannerLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Analytics.ADBadsLoaded(adUnitId, GetAdsLoadDuration(ref _badsloadStartTime), _badsCategory);
Analytics.ADBadsLoaded(AdParams.Build(adUnitId, adInfo,
duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory));
OnBannerLoaded?.Invoke();
}
private void OnBannerFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
{
// Analytics.ADBadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _badsloadStartTime), _badsCategory);
Analytics.ADBadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _badsloadStartTime), category: _badsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
}
private void OnBannerClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Analytics.ADBadsClick(adUnitId, _badsCategory);
Analytics.ADBadsClick(AdParams.Build(adUnitId, adInfo, _badsCategory));
}
private void OnBannerImpEvent(string adUnitId)
{
// Analytics.ADBadsClick(adUnitId, _badsCategory);
Analytics.ADBadsImp(AdParams.Build(adUnitId, category: _badsCategory));
}
#endregion
#region Interstitial Ads
private string _iadsCategory = "main";
private int _interstitialRetryAttempt;
protected float _iadsLoadStartTime;
private Action _interstitialDismissAction;
public virtual void RequestInterstitialAD()
{
if (!CanLoadAds())
return;
LoadMaxInterstitial();
}
protected void LoadMaxInterstitial()
{
OnLoadIads();
var id = GetInterstitialID();
Analytics.ADIadsLoad(AdParams.Build(id));
MaxSdk.LoadInterstitial(id);
}
public void OnLoadIads()
{
_iadsLoadStartTime = Time.realtimeSinceStartup;
}
public bool IsInterstitialADReady()
{
if (!IsInitialized)
return false;
return MaxSdk.IsInterstitialReady(GetInterstitialID());
}
/// <summary>
/// 显示插屏广告
/// </summary>
/// <param name="rewardAction">广告奖励回调</param>
/// <param name="failAction">广告失败回调</param>
/// <param name="dismissAction">广告界面关闭回调</param>
public virtual void ShowInterstitialAD(string category, Action dismissAction = null)
{
if (!IsInitialized)
{
this.LogWarning("广告未初始化完成,无法显示插屏广告");
return;
}
if (!IsInterstitialADReady())
{
this.LogWarning("插屏没有加载准备好,无法显示插屏广告");
return;
}
_iadsCategory = category;
_interstitialDismissAction = dismissAction;
MaxSdk.ShowInterstitial(GetInterstitialID());
RequestInterstitialAD(); // 直接加载下一个广告
}
protected virtual void OnInterstitialLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad is ready to be shown. MaxSdk.IsInterstitialReady(interstitialAdUnitId) will now return 'true'
// Reset retry attempt
// Analytics.ADIadsLoaded(adUnitId, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory));
_interstitialRetryAttempt = 0;
OnInterstitialLoaded?.Invoke();
}
protected virtual void OnInterstitialFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
{
// Interstitial ad failed to load
// We recommend retrying with exponentially higher delays up to a maximum delay (in this case 64 seconds)
this.LogError(
$"OnInterstitialFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
_interstitialRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(3, _interstitialRetryAttempt));
DelayCall((float)retryDelay, RequestInterstitialAD);
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
OnInterstitialFailed?.Invoke();
}
protected virtual void InterstitialFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo,
MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad failed to display. We recommend loading the next ad
this.LogError(
$"InterstitialFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADIadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _iadsLoadStartTime), _iadsCategory);
Analytics.ADIadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
DelayCall(2.0f, RequestInterstitialAD);
}
protected virtual void OnInterstitialDisplayEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Analytics.ADIadsImp(adUnitId, _iadsCategory);
Analytics.ADIadsImp(AdParams.Build(adUnitId, category: _iadsCategory));
}
protected virtual void OnInterstitialClickEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Analytics.ADIadsClick(adUnitId, _iadsCategory);
Analytics.ADIadsClick(AdParams.Build(adUnitId, category: _iadsCategory));
}
protected virtual void OnInterstitialDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Interstitial ad is hidden. Pre-load the next ad
_interstitialDismissAction?.Invoke();
// Analytics.ADIadsClose(adUnitId, _iadsCategory);
Analytics.ADIadsClose(AdParams.Build(adUnitId, category: _iadsCategory));
//延时加载下一个广告
DelayCall(2.0f, RequestInterstitialAD);
}
#endregion
#region Rewarded Ads
private string _rewardCategory = "main";
private int _rewardRetryAttempt;
protected float _radsLoadStartTime;
private Action _rewardAction;
private Action<string> _failAction;
private Action _dismissAction;
public virtual void RequestRewardedAD()
{
if (!IsInitialized)
return;
LoadMaxRewardAd();
}
/// <summary>
/// 默认加载 MAX 广告逻辑
/// </summary>
protected void LoadMaxRewardAd(string unitId = "")
{
OnLoadRads();
var id = GetRewardedVideoID();
Analytics.ADRadsLoad(AdParams.Build(id)); // 上报打点
MaxSdk.LoadRewardedAd(id);
}
public void OnLoadRads()
{
_radsLoadStartTime = Time.realtimeSinceStartup;
}
public virtual bool IsRewardedADReady()
{
if (!IsInitialized)
return false;
return MaxSdk.IsRewardedAdReady(GetRewardedVideoID());
}
/// <summary>
/// 显示激励视频广告
/// </summary>
/// <param name="rewardAction">广告奖励回调</param>
/// <param name="failAction">广告失败回调</param>
/// <param name="dismissAction">广告界面关闭回调</param>
public virtual void ShowRewardedAD(string category, Action rewardAction = null,
Action<string> failAction = null, Action dismissAction = null)
{
if (!IsInitialized)
{
this.LogWarning("广告未初始化完成,无法显示视频广告");
return;
}
if (!IsRewardedADReady())
{
this.LogWarning("广告没有准备好,无法显示视频广告");
return;
}
_rewardCategory = category;
_rewardAction = rewardAction;
_failAction = failAction;
_dismissAction = dismissAction;
MaxSdk.ShowRewardedAd(GetRewardedVideoID());
RequestRewardedAD();
}
protected virtual void OnRewardedAdLoadedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
// Rewarded ad is ready to be shown. MaxSdk.IsRewardedAdReady(rewardedAdUnitId) will now return 'true'
// Reset retry attempt
// this.Log("OnRewardedAdLoadedEvent");
// Analytics.ADRadsLoaded(adUnitId, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsLoaded(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _iadsLoadStartTime), category: _iadsCategory));
_rewardRetryAttempt = 0;
OnRewardLoaded?.Invoke();
}
protected virtual void OnRewardedAdFailedEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo)
{
// Rewarded ad failed to load
// We recommend retrying with exponentially higher delays up to a maximum delay (in this case 64 seconds)
this.LogError(
$"OnRewardedAdFailedEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_rewardRetryAttempt++;
double retryDelay = Math.Pow(2, Math.Min(3, _rewardRetryAttempt));
DelayCall((float)retryDelay, RequestRewardedAD);
OnRewardFailed?.Invoke();
}
protected virtual void OnRewardedAdFailedToDisplayEvent(string adUnitId, MaxSdkBase.ErrorInfo errorInfo,
MaxSdkBase.AdInfo arg3)
{
// Rewarded ad failed to display. We recommend loading the next ad
this.LogError(
$"OnRewardedAdFailedToDisplayEvent AdLoadFailureInfo:{errorInfo.AdLoadFailureInfo}, Message: {errorInfo.Message}");
// Analytics.ADRadsFailed(adUnitId, (int)errorInfo.Code, GetAdsLoadDuration(ref _radsLoadStartTime), _rewardCategory);
Analytics.ADRadsFailed(AdParams.Build(adUnitId,
duration: GetAdsLoadDuration(ref _radsLoadStartTime), category: _rewardCategory,
errorCode: (int)errorInfo.Code,
waterfallName: errorInfo?.WaterfallInfo?.Name ?? ""));
_failAction?.Invoke("OnRewardedAdFailedToDisplayEvent");
DelayCall(2.0f, RequestRewardedAD);
OnRewardFailed?.Invoke();
}
protected virtual void OnRewardedAdDisplayedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdDisplayedEvent");
// Analytics.ADRadsImp(adUnitId, _rewardCategory);
Analytics.ADRadsImp(AdParams.Build(adUnitId, category: _rewardCategory));
}
protected virtual void OnRewardedAdClickedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdClickedEvent");
// Analytics.ADRadsClick(adUnitId, _rewardCategory);
Analytics.ADRadsClick(AdParams.Build(adUnitId, category: _rewardCategory));
}
protected virtual void OnRewardedAdDismissedEvent(string adUnitId, MaxSdkBase.AdInfo adInfo)
{
this.Log("OnRewardedAdDismissedEvent");
// Analytics.ADRadsClose(adUnitId, _rewardCategory);
Analytics.ADRadsClose(AdParams.Build(adUnitId, category: _rewardCategory));
_dismissAction?.Invoke();
//延时加载下一个广告
DelayCall(2.0f, RequestRewardedAD);
}
protected virtual void OnRewardedAdReceivedRewardEvent(string adUnitId, MaxSdk.Reward reward,
MaxSdkBase.AdInfo arg3)
{
this.Log("OnRewardedAdReceivedRewardEvent");
// Analytics.ADRadsRewarded(adUnitId, _rewardCategory);
Analytics.ADRadsRewarded(AdParams.Build(adUnitId, category: _rewardCategory));
// Rewarded ad was displayed and user should receive the reward
_rewardAction?.Invoke();
}
#endregion
#region Ad Settings
protected virtual string GetRewardedVideoID()
{
return GuruSettings.Instance.ADSetting.GetRewardedVideoID();
}
protected virtual string GetInterstitialID()
{
return GuruSettings.Instance.ADSetting.GetInterstitialID();
}
protected virtual string GetBannerID()
{
return GuruSettings.Instance.ADSetting.GetBannerID();
}
#endregion
#region MaxDebugView
public void ShowMaxDebugPanel()
{
if (!IsInitialized) return;
#if !UNITY_EDITOR
MaxSdk.ShowMediationDebugger();
#endif
}
#endregion
#region DelayCall
private void DelayCall(float time, Action callback)
{
CoroutineHelper.Instance.StartDelayed(time, callback);
}
#endregion
}
}