Playvoi/Assets/ShiroginSDK/Runtime/Services/Implementations/Ads/AdsService.cs
2025-10-30 22:48:16 +03:00

274 lines
No EOL
9.3 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 ShiroginSDK.Runtime.Core.SDK;
using ShiroginSDK.Runtime.Core.Utils;
using ShiroginSDK.Runtime.Modules.Data.Scripts;
using ShiroginSDK.Runtime.Modules.Data.Scripts.Enums;
using ShiroginSDK.Runtime.Modules.Events;
using ShiroginSDK.Runtime.Services.Base;
using ShiroginSDK.Runtime.Services.Interfaces;
using UnityEngine;
namespace ShiroginSDK.Runtime.Services.Implementations.Ads
{
/// <summary>
/// Handles Rewarded, Interstitial and Banner ads using AppLovin MAX SDK.
/// </summary>
public class AdsService : ServiceBase, IAdsService
{
private ShiroginConfig _config;
private int _retryAttempt;
private bool _canShowInterstitial;
private int _addShowInterstitialTime;
private Action<bool> _shouldReward;
private Coroutine _interstitialCycle;
private IDataService _dataService;
private IEventService _eventService;
// ----------------------------------------------------
// Initialization
// ----------------------------------------------------
protected override void OnInitialize()
{
// Resolve dependencies
_dataService = ServiceLocator.Get<IDataService>();
_eventService = ServiceLocator.Get<IEventService>();
_config = ShiroginConfig.Load();
if (string.IsNullOrEmpty(_config.applovinSdkKey))
{
Debug.LogError("[ShiroginSDK] Missing AppLovin SDK key in SDKConfig.");
return;
}
MaxSdk.SetSdkKey(_config.applovinSdkKey);
MaxSdk.InitializeSdk();
InitializeRewardedAds();
var storeData = _dataService.Get<StoreData>();
if (!storeData.HasRemovedAds)
{
InitializeInterstitialAds();
InitializeBannerAds();
}
if (Application.internetReachability != NetworkReachability.NotReachable)
_interstitialCycle = CoroutineRunner.Start(InterstitialCycle());
}
protected override void OnDispose()
{
if (_interstitialCycle != null)
CoroutineRunner.Stop(_interstitialCycle);
}
// ----------------------------------------------------
// Rewarded Ads
// ----------------------------------------------------
public bool IsRewardedReady => MaxSdk.IsRewardedAdReady(GetRewardedId());
public void ShowRewarded(Action<bool> onComplete)
{
_shouldReward = onComplete;
var economy = _dataService.Get<EconomyData>();
if (economy.RewardedTicket > 0)
{
economy.SpendCurrency(CurrencyType.RewardedTicket, 1);
_shouldReward?.Invoke(true);
return;
}
if (Application.internetReachability == NetworkReachability.NotReachable)
{
_eventService.Invoke(new ShiroginEvents.Connection.NoConnectionEvent());
_shouldReward?.Invoke(false);
return;
}
// 🔹 Tam buraya ekle (önce reklam hazır mı kontrol et)
if (!MaxSdk.IsRewardedAdReady(GetRewardedId()))
{
Debug.LogWarning("[AdsService] ⚠️ Rewarded ad not ready — NoAdsAvailable event triggered.");
_eventService.Invoke(new ShiroginEvents.Ads.RewardedAdUnavailableEvent()); // Popup
_shouldReward?.Invoke(false);
return;
}
// 🔹 Eğer buraya geldiyse reklam hazır, güvenle göster
MaxSdk.ShowRewardedAd(GetRewardedId());
}
private void InitializeRewardedAds()
{
// Reset retry counter
_retryAttempt = 0;
// --- When ad is successfully loaded
MaxSdkCallbacks.Rewarded.OnAdLoadedEvent += (adUnitId, info) =>
{
_retryAttempt = 0;
Debug.Log($"[AdsService] ✅ Rewarded loaded: {adUnitId}");
};
// --- When ad fails to load
MaxSdkCallbacks.Rewarded.OnAdLoadFailedEvent += (adUnitId, error) =>
{
_retryAttempt++;
var retryDelay = Math.Pow(2, Math.Min(6, _retryAttempt));
Debug.LogWarning($"[AdsService] ⚠️ Rewarded load failed. Retrying in {retryDelay:0.0}s...");
CoroutineRunner.InvokeDelayed(LoadRewardedAd, (float)retryDelay);
};
// --- When ad is displayed
MaxSdkCallbacks.Rewarded.OnAdDisplayedEvent += (adUnitId, info) =>
{
Debug.Log($"[AdsService] ▶️ Rewarded ad displayed: {adUnitId}");
};
// --- When ad fails to display
MaxSdkCallbacks.Rewarded.OnAdDisplayFailedEvent += (adUnitId, error, info) =>
{
Debug.LogError($"[AdsService] ❌ Rewarded display failed: {error.Message}");
LoadRewardedAd(); // Retry load immediately
};
// --- When ad is hidden (after being watched or skipped)
MaxSdkCallbacks.Rewarded.OnAdHiddenEvent += (adUnitId, info) =>
{
Debug.Log("[AdsService] 🧹 Rewarded closed. Reloading...");
LoadRewardedAd(); // Always reload when ad is closed
};
// --- When user earns reward
MaxSdkCallbacks.Rewarded.OnAdReceivedRewardEvent += OnRewardedCompleted;
// Initial load
LoadRewardedAd();
}
private void OnRewardedCompleted(string id, MaxSdkBase.Reward reward, MaxSdkBase.AdInfo info)
{
_shouldReward?.Invoke(true);
_eventService.Invoke(new ShiroginEvents.Ads.AdAnalyticsEvent(info.NetworkName, id, info.AdFormat + "_Reward",
true, info.Revenue));
_addShowInterstitialTime += 50;
// ✅ Yeni reklam yükle (önemli!)
LoadRewardedAd();
}
private void LoadRewardedAd()
{
MaxSdk.LoadRewardedAd(GetRewardedId());
}
// ----------------------------------------------------
// Interstitial Ads
// ----------------------------------------------------
private IEnumerator InterstitialCycle()
{
while (true)
{
yield return new WaitForSeconds(180f + _addShowInterstitialTime);
_canShowInterstitial = true;
_addShowInterstitialTime = 0;
yield return new WaitUntil(() => !_canShowInterstitial);
}
}
private void InitializeInterstitialAds()
{
MaxSdkCallbacks.Interstitial.OnAdLoadedEvent += (_, _) => _retryAttempt = 0;
MaxSdkCallbacks.Interstitial.OnAdLoadFailedEvent += (_, _) =>
{
_retryAttempt++;
var delay = Math.Pow(2, Math.Min(6, _retryAttempt));
CoroutineRunner.InvokeDelayed(LoadInterstitial, (float)delay);
};
LoadInterstitial();
}
private void LoadInterstitial()
{
MaxSdk.LoadInterstitial(GetInterstitialId());
}
public void ShowInterstitial(bool forceShow = false)
{
var storeData = _dataService.Get<StoreData>();
if (storeData.HasRemovedAds)
return;
if ((forceShow || _canShowInterstitial) && MaxSdk.IsInterstitialReady(GetInterstitialId()))
{
MaxSdk.ShowInterstitial(GetInterstitialId());
LoadInterstitial();
_canShowInterstitial = false;
}
}
// ----------------------------------------------------
// Banner Ads
// ----------------------------------------------------
private void InitializeBannerAds()
{
MaxSdk.CreateBanner(GetBannerId(), MaxSdkBase.BannerPosition.BottomCenter);
MaxSdkCallbacks.Banner.OnAdLoadedEvent += (_, _) => { };
MaxSdkCallbacks.Banner.OnAdLoadFailedEvent += (_, _) => { };
}
public void CreateBanner(bool show)
{
DestroyBanner();
MaxSdk.CreateBanner(GetBannerId(), MaxSdkBase.BannerPosition.BottomCenter);
if (show) MaxSdk.ShowBanner(GetBannerId());
}
public void ShowBanner()
{
MaxSdk.ShowBanner(GetBannerId());
}
public void HideBanner()
{
MaxSdk.HideBanner(GetBannerId());
}
public void DestroyBanner()
{
MaxSdk.DestroyBanner(GetBannerId());
}
// ----------------------------------------------------
// Helpers
// ----------------------------------------------------
#if UNITY_IOS
private string GetRewardedId() => _config.rewardedAdUnitIdIos;
private string GetInterstitialId() => _config.interstitialAdUnitIdIos;
private string GetBannerId() => _config.bannerAdUnitIdIos;
#else
private string GetRewardedId()
{
return _config.rewardedAdUnitIdDrd;
}
private string GetInterstitialId()
{
return _config.interstitialAdUnitIdDrd;
}
private string GetBannerId()
{
return _config.bannerAdUnitIdDrd;
}
#endif
}
}