adservice added
This commit is contained in:
8
Assets/Darkmatter/Code/Services/Ads.meta
Normal file
8
Assets/Darkmatter/Code/Services/Ads.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a320ad839a14f578bb9ff149807ed84
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Darkmatter/Code/Services/Ads/Installers.meta
Normal file
8
Assets/Darkmatter/Code/Services/Ads/Installers.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd05451b7a0c4e04ae9521e8052ee1e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using Darkmatter.Core.Contracts.Services.Ads;
|
||||
using Darkmatter.Core.Data.Static.Services.Ads;
|
||||
using Darkmatter.Libs.Installers;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
using VContainer.Unity;
|
||||
|
||||
namespace Darkmatter.Services.Ads
|
||||
{
|
||||
public class AdServiceModule : MonoBehaviour, IModule
|
||||
{
|
||||
[SerializeField] private AdUnitCatalogSO adUnitCatalog;
|
||||
[SerializeField] private AdMobAdService adService;
|
||||
|
||||
public void Register(IContainerBuilder builder)
|
||||
{
|
||||
if (adUnitCatalog != null)
|
||||
builder.RegisterComponent(adUnitCatalog);
|
||||
|
||||
var resolved = adService;
|
||||
if (resolved == null) resolved = GetComponent<AdMobAdService>();
|
||||
if (resolved == null) resolved = GetComponentInChildren<AdMobAdService>(includeInactive: true);
|
||||
if (resolved == null) resolved = FindFirstObjectByType<AdMobAdService>(FindObjectsInactive.Include);
|
||||
|
||||
if (resolved != null)
|
||||
builder.RegisterComponent<IAdService>(resolved);
|
||||
else
|
||||
Debug.LogError("[AdServiceModule] No AdMobAdService component found. Assign 'adService' field or add AdMobAdService MonoBehaviour to scene.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a17cb41935543a6b4f67be8f398d774
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
25
Assets/Darkmatter/Code/Services/Ads/Services.Ads.asmdef
Normal file
25
Assets/Darkmatter/Code/Services/Ads/Services.Ads.asmdef
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "Services.Ads",
|
||||
"rootNamespace": "Darkmatter.Services.Ads",
|
||||
"references": [
|
||||
"GUID:6a0a834eb41764f12ba55c3fb04a40cb",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
|
||||
"GUID:c1c03c0e5b2f4412b9f2be1c20d6a9b1"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.google.ads.mobile",
|
||||
"expression": "1.0.0",
|
||||
"define": "GOOGLE_MOBILE_ADS"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 662a8e56a1724c84ad8c10211211f0d5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Assets/Darkmatter/Code/Services/Ads/Systems.meta
Normal file
8
Assets/Darkmatter/Code/Services/Ads/Systems.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fbb9ad075cb419095482b3d74c4311c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
534
Assets/Darkmatter/Code/Services/Ads/Systems/AdMobAdService.cs
Normal file
534
Assets/Darkmatter/Code/Services/Ads/Systems/AdMobAdService.cs
Normal file
@@ -0,0 +1,534 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Darkmatter.Core.Contracts.Services.Ads;
|
||||
using Darkmatter.Core.Data.Dynamic.Services.Ads;
|
||||
using Darkmatter.Core.Data.Static.Services.Ads;
|
||||
using Darkmatter.Core.Enums.Services.Ads;
|
||||
using UnityEngine;
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
using GoogleMobileAds.Api;
|
||||
#endif
|
||||
|
||||
namespace Darkmatter.Services.Ads
|
||||
{
|
||||
public class AdMobAdService : MonoBehaviour, IAdService
|
||||
{
|
||||
[SerializeField] private AdUnitCatalogSO catalog;
|
||||
[Tooltip("Auto-reload after dismiss/failure for non-banner formats.")]
|
||||
[SerializeField] private bool autoReload = true;
|
||||
[Tooltip("Seconds between auto-reload retries on failure.")]
|
||||
[SerializeField, Min(1f)] private float reloadDelaySeconds = 5f;
|
||||
|
||||
public bool IsInitialized => _initialized;
|
||||
public event Action<AdFormat, AdLoadState> LoadStateChanged;
|
||||
|
||||
private bool _initialized;
|
||||
private bool _hasUserConsent = true;
|
||||
private bool _isChildDirected;
|
||||
private CancellationTokenSource _lifetimeCts;
|
||||
|
||||
private readonly Dictionary<AdFormat, AdLoadState> _states = new();
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
private InterstitialAd _interstitial;
|
||||
private RewardedAd _rewarded;
|
||||
private RewardedInterstitialAd _rewardedInterstitial;
|
||||
private AppOpenAd _appOpen;
|
||||
private BannerView _banner;
|
||||
#endif
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_lifetimeCts = new CancellationTokenSource();
|
||||
foreach (AdFormat fmt in Enum.GetValues(typeof(AdFormat)))
|
||||
_states[fmt] = AdLoadState.Idle;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_lifetimeCts?.Cancel();
|
||||
_lifetimeCts?.Dispose();
|
||||
_lifetimeCts = null;
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
_interstitial?.Destroy();
|
||||
_rewarded?.Destroy();
|
||||
_rewardedInterstitial?.Destroy();
|
||||
_appOpen?.Destroy();
|
||||
_banner?.Destroy();
|
||||
#endif
|
||||
}
|
||||
|
||||
public async UniTask InitializeAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
if (_initialized) return;
|
||||
if (catalog == null)
|
||||
{
|
||||
Debug.LogError("[AdMobAdService] No AdUnitCatalogSO assigned.");
|
||||
return;
|
||||
}
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
ApplyRequestConfiguration();
|
||||
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
MobileAds.Initialize(_ => tcs.TrySetResult(true));
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
await tcs.Task;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
Debug.Log("[AdMobAdService] Initialized.");
|
||||
#else
|
||||
await UniTask.CompletedTask;
|
||||
_initialized = true;
|
||||
Debug.LogWarning("[AdMobAdService] GOOGLE_MOBILE_ADS not defined. Service will no-op. Add scripting define after importing Google Mobile Ads SDK.");
|
||||
#endif
|
||||
}
|
||||
|
||||
public async UniTask<bool> LoadAsync(AdFormat format, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
Debug.LogWarning("[AdMobAdService] Load called before init.");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
string unitId = catalog.GetUnitId(format, Application.platform);
|
||||
if (string.IsNullOrEmpty(unitId))
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] No unit ID for {format} on {Application.platform}.");
|
||||
return false;
|
||||
}
|
||||
|
||||
SetState(format, AdLoadState.Loading);
|
||||
var request = new AdRequest();
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case AdFormat.Interstitial:
|
||||
return await LoadInterstitialAsync(unitId, request, cancellationToken);
|
||||
case AdFormat.Rewarded:
|
||||
return await LoadRewardedAsync(unitId, request, cancellationToken);
|
||||
case AdFormat.RewardedInterstitial:
|
||||
return await LoadRewardedInterstitialAsync(unitId, request, cancellationToken);
|
||||
case AdFormat.AppOpen:
|
||||
return await LoadAppOpenAsync(unitId, request, cancellationToken);
|
||||
case AdFormat.Banner:
|
||||
Debug.LogWarning("[AdMobAdService] Use ShowBannerAsync for banners.");
|
||||
SetState(format, AdLoadState.Failed);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
await UniTask.CompletedTask;
|
||||
SetState(format, AdLoadState.Failed);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool IsReady(AdFormat format)
|
||||
{
|
||||
if (!_initialized) return false;
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
return format switch
|
||||
{
|
||||
AdFormat.Interstitial => _interstitial != null && _interstitial.CanShowAd(),
|
||||
AdFormat.Rewarded => _rewarded != null && _rewarded.CanShowAd(),
|
||||
AdFormat.RewardedInterstitial => _rewardedInterstitial != null && _rewardedInterstitial.CanShowAd(),
|
||||
AdFormat.AppOpen => _appOpen != null && _appOpen.CanShowAd(),
|
||||
_ => false
|
||||
};
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public async UniTask<AdShowResult> ShowAsync(AdFormat format, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_initialized) return AdShowResult.Failure("Not initialized.");
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
if (!IsReady(format))
|
||||
{
|
||||
bool loaded = await LoadAsync(format, cancellationToken);
|
||||
if (!loaded) return AdShowResult.Failure($"{format} failed to load.");
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case AdFormat.Interstitial: return await ShowInterstitialAsync(cancellationToken);
|
||||
case AdFormat.Rewarded: return await ShowRewardedAsync(cancellationToken);
|
||||
case AdFormat.RewardedInterstitial: return await ShowRewardedInterstitialAsync(cancellationToken);
|
||||
case AdFormat.AppOpen: return await ShowAppOpenAsync(cancellationToken);
|
||||
}
|
||||
return AdShowResult.Failure($"{format} not supported by ShowAsync.");
|
||||
#else
|
||||
await UniTask.CompletedTask;
|
||||
return AdShowResult.Failure("GOOGLE_MOBILE_ADS not defined.");
|
||||
#endif
|
||||
}
|
||||
|
||||
public async UniTask<bool> ShowBannerAsync(BannerSize size, BannerPosition position, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_initialized) return false;
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
string unitId = catalog.GetUnitId(AdFormat.Banner, Application.platform);
|
||||
if (string.IsNullOrEmpty(unitId)) return false;
|
||||
|
||||
_banner?.Destroy();
|
||||
_banner = new BannerView(unitId, MapBannerSize(size), MapBannerPosition(position));
|
||||
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
_banner.OnBannerAdLoaded += () => tcs.TrySetResult(true);
|
||||
_banner.OnBannerAdLoadFailed += err =>
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] Banner load failed: {err}");
|
||||
tcs.TrySetResult(false);
|
||||
};
|
||||
|
||||
SetState(AdFormat.Banner, AdLoadState.Loading);
|
||||
_banner.LoadAd(new AdRequest());
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
bool ok = await tcs.Task;
|
||||
SetState(AdFormat.Banner, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
||||
return ok;
|
||||
}
|
||||
#else
|
||||
await UniTask.CompletedTask;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void HideBanner()
|
||||
{
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
_banner?.Hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
public void DestroyBanner()
|
||||
{
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
_banner?.Destroy();
|
||||
_banner = null;
|
||||
SetState(AdFormat.Banner, AdLoadState.Idle);
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetConsent(bool hasUserConsent, bool isChildDirected)
|
||||
{
|
||||
_hasUserConsent = hasUserConsent;
|
||||
_isChildDirected = isChildDirected;
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
if (_initialized) ApplyRequestConfiguration();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GOOGLE_MOBILE_ADS
|
||||
private void ApplyRequestConfiguration()
|
||||
{
|
||||
var config = new RequestConfiguration
|
||||
{
|
||||
TagForChildDirectedTreatment = _isChildDirected
|
||||
? TagForChildDirectedTreatment.True
|
||||
: TagForChildDirectedTreatment.Unspecified,
|
||||
TagForUnderAgeOfConsent = _hasUserConsent
|
||||
? TagForUnderAgeOfConsent.Unspecified
|
||||
: TagForUnderAgeOfConsent.True
|
||||
};
|
||||
|
||||
if (catalog.TestDeviceIds is { Count: > 0 })
|
||||
{
|
||||
config.TestDeviceIds = new List<string>(catalog.TestDeviceIds);
|
||||
}
|
||||
|
||||
MobileAds.SetRequestConfiguration(config);
|
||||
}
|
||||
|
||||
private async UniTask<bool> LoadInterstitialAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
InterstitialAd.Load(unitId, request, (ad, error) =>
|
||||
{
|
||||
if (error != null || ad == null)
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] Interstitial load failed: {error}");
|
||||
tcs.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
_interstitial?.Destroy();
|
||||
_interstitial = ad;
|
||||
WireFullScreenEvents(ad, AdFormat.Interstitial);
|
||||
tcs.TrySetResult(true);
|
||||
});
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
bool ok = await tcs.Task;
|
||||
SetState(AdFormat.Interstitial, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<bool> LoadRewardedAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
RewardedAd.Load(unitId, request, (ad, error) =>
|
||||
{
|
||||
if (error != null || ad == null)
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] Rewarded load failed: {error}");
|
||||
tcs.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
_rewarded?.Destroy();
|
||||
_rewarded = ad;
|
||||
WireFullScreenEvents(ad, AdFormat.Rewarded);
|
||||
tcs.TrySetResult(true);
|
||||
});
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
bool ok = await tcs.Task;
|
||||
SetState(AdFormat.Rewarded, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<bool> LoadRewardedInterstitialAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
RewardedInterstitialAd.Load(unitId, request, (ad, error) =>
|
||||
{
|
||||
if (error != null || ad == null)
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] RewardedInterstitial load failed: {error}");
|
||||
tcs.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
_rewardedInterstitial?.Destroy();
|
||||
_rewardedInterstitial = ad;
|
||||
WireFullScreenEvents(ad, AdFormat.RewardedInterstitial);
|
||||
tcs.TrySetResult(true);
|
||||
});
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
bool ok = await tcs.Task;
|
||||
SetState(AdFormat.RewardedInterstitial, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<bool> LoadAppOpenAsync(string unitId, AdRequest request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<bool>();
|
||||
AppOpenAd.Load(unitId, request, (ad, error) =>
|
||||
{
|
||||
if (error != null || ad == null)
|
||||
{
|
||||
Debug.LogWarning($"[AdMobAdService] AppOpen load failed: {error}");
|
||||
tcs.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
_appOpen?.Destroy();
|
||||
_appOpen = ad;
|
||||
WireFullScreenEvents(ad, AdFormat.AppOpen);
|
||||
tcs.TrySetResult(true);
|
||||
});
|
||||
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
{
|
||||
bool ok = await tcs.Task;
|
||||
SetState(AdFormat.AppOpen, ok ? AdLoadState.Loaded : AdLoadState.Failed);
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<AdShowResult> ShowInterstitialAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
||||
Action onClosed = () => tcs.TrySetResult(AdShowResult.Success());
|
||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
||||
|
||||
_interstitial.OnAdFullScreenContentClosed += onClosed;
|
||||
_interstitial.OnAdFullScreenContentFailed += onFailed;
|
||||
_interstitial.Show();
|
||||
|
||||
try
|
||||
{
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
return await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_interstitial != null)
|
||||
{
|
||||
_interstitial.OnAdFullScreenContentClosed -= onClosed;
|
||||
_interstitial.OnAdFullScreenContentFailed -= onFailed;
|
||||
}
|
||||
ScheduleReload(AdFormat.Interstitial);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<AdShowResult> ShowRewardedAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
||||
bool earned = false;
|
||||
AdReward reward = default;
|
||||
|
||||
Action onClosed = () => tcs.TrySetResult(earned ? AdShowResult.WithReward(reward) : AdShowResult.Success());
|
||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
||||
|
||||
_rewarded.OnAdFullScreenContentClosed += onClosed;
|
||||
_rewarded.OnAdFullScreenContentFailed += onFailed;
|
||||
_rewarded.Show(r =>
|
||||
{
|
||||
earned = true;
|
||||
reward = new AdReward(r.Type, r.Amount);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
return await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_rewarded != null)
|
||||
{
|
||||
_rewarded.OnAdFullScreenContentClosed -= onClosed;
|
||||
_rewarded.OnAdFullScreenContentFailed -= onFailed;
|
||||
}
|
||||
ScheduleReload(AdFormat.Rewarded);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<AdShowResult> ShowRewardedInterstitialAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
||||
bool earned = false;
|
||||
AdReward reward = default;
|
||||
|
||||
Action onClosed = () => tcs.TrySetResult(earned ? AdShowResult.WithReward(reward) : AdShowResult.Success());
|
||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
||||
|
||||
_rewardedInterstitial.OnAdFullScreenContentClosed += onClosed;
|
||||
_rewardedInterstitial.OnAdFullScreenContentFailed += onFailed;
|
||||
_rewardedInterstitial.Show(r =>
|
||||
{
|
||||
earned = true;
|
||||
reward = new AdReward(r.Type, r.Amount);
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
return await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_rewardedInterstitial != null)
|
||||
{
|
||||
_rewardedInterstitial.OnAdFullScreenContentClosed -= onClosed;
|
||||
_rewardedInterstitial.OnAdFullScreenContentFailed -= onFailed;
|
||||
}
|
||||
ScheduleReload(AdFormat.RewardedInterstitial);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask<AdShowResult> ShowAppOpenAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var tcs = new UniTaskCompletionSource<AdShowResult>();
|
||||
Action onClosed = () => tcs.TrySetResult(AdShowResult.Success());
|
||||
Action<AdError> onFailed = err => tcs.TrySetResult(AdShowResult.Failure(err?.GetMessage()));
|
||||
|
||||
_appOpen.OnAdFullScreenContentClosed += onClosed;
|
||||
_appOpen.OnAdFullScreenContentFailed += onFailed;
|
||||
_appOpen.Show();
|
||||
|
||||
try
|
||||
{
|
||||
using (cancellationToken.Register(() => tcs.TrySetCanceled(cancellationToken)))
|
||||
return await tcs.Task;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_appOpen != null)
|
||||
{
|
||||
_appOpen.OnAdFullScreenContentClosed -= onClosed;
|
||||
_appOpen.OnAdFullScreenContentFailed -= onFailed;
|
||||
}
|
||||
ScheduleReload(AdFormat.AppOpen);
|
||||
}
|
||||
}
|
||||
|
||||
private void WireFullScreenEvents(InterstitialAd ad, AdFormat format) =>
|
||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
||||
|
||||
private void WireFullScreenEvents(RewardedAd ad, AdFormat format) =>
|
||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
||||
|
||||
private void WireFullScreenEvents(RewardedInterstitialAd ad, AdFormat format) =>
|
||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
||||
|
||||
private void WireFullScreenEvents(AppOpenAd ad, AdFormat format) =>
|
||||
ad.OnAdFullScreenContentClosed += () => SetState(format, AdLoadState.Idle);
|
||||
|
||||
private void ScheduleReload(AdFormat format)
|
||||
{
|
||||
if (!autoReload || _lifetimeCts == null) return;
|
||||
ReloadAfterDelayAsync(format, _lifetimeCts.Token).Forget();
|
||||
}
|
||||
|
||||
private async UniTaskVoid ReloadAfterDelayAsync(AdFormat format, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UniTask.Delay(TimeSpan.FromSeconds(reloadDelaySeconds), cancellationToken: cancellationToken);
|
||||
await LoadAsync(format, cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
}
|
||||
|
||||
private static AdSize MapBannerSize(BannerSize size) => size switch
|
||||
{
|
||||
BannerSize.Banner => AdSize.Banner,
|
||||
BannerSize.LargeBanner => AdSize.LargeBanner,
|
||||
BannerSize.MediumRectangle => AdSize.MediumRectangle,
|
||||
BannerSize.FullBanner => AdSize.IABBanner,
|
||||
BannerSize.Leaderboard => AdSize.Leaderboard,
|
||||
BannerSize.SmartBanner => AdSize.SmartBanner,
|
||||
BannerSize.AnchoredAdaptive => AdSize.GetCurrentOrientationAnchoredAdaptiveBannerAdSizeWithWidth(AdSize.FullWidth),
|
||||
_ => AdSize.Banner
|
||||
};
|
||||
|
||||
private static AdPosition MapBannerPosition(BannerPosition position) => position switch
|
||||
{
|
||||
BannerPosition.Top => AdPosition.Top,
|
||||
BannerPosition.Bottom => AdPosition.Bottom,
|
||||
BannerPosition.TopLeft => AdPosition.TopLeft,
|
||||
BannerPosition.TopRight => AdPosition.TopRight,
|
||||
BannerPosition.BottomLeft => AdPosition.BottomLeft,
|
||||
BannerPosition.BottomRight => AdPosition.BottomRight,
|
||||
BannerPosition.Center => AdPosition.Center,
|
||||
_ => AdPosition.Bottom
|
||||
};
|
||||
#endif
|
||||
|
||||
private void SetState(AdFormat format, AdLoadState state)
|
||||
{
|
||||
_states[format] = state;
|
||||
LoadStateChanged?.Invoke(format, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 018ba83ad51c4d9a89a904ba3d21ead2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user