diff --git a/Editor/Metica.UnityEd.asmdef b/Editor/Metica.UnityEd.asmdef
index d077b21..0ab89b5 100644
--- a/Editor/Metica.UnityEd.asmdef
+++ b/Editor/Metica.UnityEd.asmdef
@@ -2,7 +2,7 @@
"name": "Metica.UnityEd",
"rootNamespace": "",
"references": [
- "GUID:c2fa3a29e8c2d344eb32bb07693f48f2"
+ "GUID:201bb3ee2b9a58648b8158bc0b3694a5"
],
"includePlatforms": [
"Editor"
diff --git a/Editor/MeticaAdsDependencies.xml b/Editor/MeticaAdsDependencies.xml
index 27b957f..2b6c216 100644
--- a/Editor/MeticaAdsDependencies.xml
+++ b/Editor/MeticaAdsDependencies.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/Editor/MeticaEditorUtilities.cs b/Editor/MeticaEditorUtilities.cs
index 6586510..7813eb9 100644
--- a/Editor/MeticaEditorUtilities.cs
+++ b/Editor/MeticaEditorUtilities.cs
@@ -2,7 +2,7 @@
using UnityEngine;
using UnityEditor;
using System.IO;
-using Metica.Unity;
+using Metica.SDK.Unity;
namespace Metica.UnityEd
{
diff --git a/Editor/MeticaUnitySdkEditor.cs b/Editor/MeticaUnitySdkEditor.cs
index 93586ea..93e2feb 100644
--- a/Editor/MeticaUnitySdkEditor.cs
+++ b/Editor/MeticaUnitySdkEditor.cs
@@ -1,8 +1,7 @@
using UnityEngine;
using UnityEditor;
using System.IO;
-
-using Metica.Unity;
+using Metica.SDK.Unity;
namespace Metica.UnityEd
{
@@ -10,7 +9,7 @@ namespace Metica.UnityEd
public class MeticaUnitySdkEditor : Editor
{
MeticaUnitySdk m_sdk = null;
- SdkConfigProvider m_configProvider = null;
+ MeticaConfigProvider m_configProvider = null;
private const string MeticaDataFolder = "Assets/Metica/Data";
@@ -40,7 +39,7 @@ public override void OnInspectorGUI()
if (!string.IsNullOrEmpty(assetPath))
{
- m_configProvider = ScriptableObject.CreateInstance();
+ m_configProvider = ScriptableObject.CreateInstance();
AssetDatabase.CreateAsset(m_configProvider, assetPath);
AssetDatabase.Refresh();
diff --git a/Runtime/ADS/Metica.ADS.asmdef b/Runtime/ADS/Metica.ADS.asmdef
index 89766e6..dcdab15 100644
--- a/Runtime/ADS/Metica.ADS.asmdef
+++ b/Runtime/ADS/Metica.ADS.asmdef
@@ -2,7 +2,6 @@
"name": "Metica.ADS",
"rootNamespace": "",
"references": [
- "Metica.SDK",
"MaxSdk.Scripts",
"Metica.Core"
],
@@ -15,4 +14,4 @@
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
-}
\ No newline at end of file
+}
diff --git a/Runtime/ADS/Metica.ADS.asmdef.meta b/Runtime/ADS/Metica.ADS.asmdef.meta
index 1823d7a..a9dbc80 100644
--- a/Runtime/ADS/Metica.ADS.asmdef.meta
+++ b/Runtime/ADS/Metica.ADS.asmdef.meta
@@ -1,3 +1,7 @@
fileFormatVersion: 2
guid: 5297a986a6e349da9a62d3434a3be1d9
-timeCreated: 1744918088
\ No newline at end of file
+AssemblyDefinitionImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/ADS/MeticaAds.cs b/Runtime/ADS/MeticaAds.cs
index 3e0b3ff..ca964fb 100644
--- a/Runtime/ADS/MeticaAds.cs
+++ b/Runtime/ADS/MeticaAds.cs
@@ -2,12 +2,12 @@
using System.Threading.Tasks;
using Metica.Core;
-using Metica.SDK;
using UnityEngine.Assertions;
// ReSharper disable once CheckNamespace
namespace Metica.ADS
{
+ // TODO: make the whole class internal
public static class MeticaAds
{
public const string TAG = "MeticaUnityPlugin";
@@ -23,7 +23,7 @@ static MeticaAds()
// Check for Unity Editor first since the editor also responds to the currently selected platform.
PlatformDelegate = GetUnityPlayerDelegate();
#elif UNITY_ANDROID
- PlatformDelegate = new Android.AndroidDelegate(AndroidUnityBridge.UnityBridgeClass, AndroidUnityBridge.MeticaAdsExternalTrackerClass);
+ PlatformDelegate = new Android.AndroidDelegate(AndroidUnityBridge.UnityBridgeClass);
#elif UNITY_IPHONE || UNITY_IOS
PlatformDelegate = new IOS.IOSDelegate();
#else
@@ -55,20 +55,14 @@ static MeticaAds()
PlatformDelegate.RewardedAdRevenuePaid += MeticaAdsCallbacks.Rewarded.OnAdRevenuePaidInternal;
}
- public static async Task InitializeAsync(MeticaConfiguration configuration)
- {
- var result = await InitializeWithResultAsync(configuration);
- return result.IsMeticaAdsEnabled;
- }
-
- public static async Task InitializeWithResultAsync(MeticaConfiguration configuration)
+ public static async Task InitializeAsync(MeticaConfiguration configuration)
{
return await PlatformDelegate.InitializeAsync(
- MeticaSdk.ApiKey,
- MeticaSdk.AppId,
- MeticaSdk.CurrentUserId,
- MeticaSdk.Version,
- MeticaSdk.BaseEndpoint,
+ configuration.ApiKey,
+ configuration.AppId,
+ configuration.UserId,
+ configuration.Version,
+ configuration.BaseEndpoint,
configuration
);
}
@@ -86,7 +80,6 @@ public static void CreateBanner(string bannerAdUnitId, MeticaBannerPosition posi
// Banner ad methods
public static void ShowBanner(string adUnitId)
{
-
PlatformDelegate.ShowBanner(adUnitId);
}
public static void HideBanner(string adUnitId)
@@ -100,53 +93,31 @@ public static void DestroyBanner(string adUnitId)
}
// Interstitial ad methods
- public static void LoadInterstitial()
+ public static void LoadInterstitial(string interstitialAdUnitId)
{
- PlatformDelegate.LoadInterstitial();
+ PlatformDelegate.LoadInterstitial(interstitialAdUnitId);
}
- public static void ShowInterstitial()
+ public static void ShowInterstitial(string interstitialAdUnitId)
{
- PlatformDelegate.ShowInterstitial();
+ PlatformDelegate.ShowInterstitial(interstitialAdUnitId);
}
- public static bool IsInterstitialReady()
+ public static bool IsInterstitialReady(string interstitialAdUnitId)
{
- return PlatformDelegate.IsInterstitialReady();
+ return PlatformDelegate.IsInterstitialReady(interstitialAdUnitId);
}
// Rewarded ad methods
- public static void LoadRewarded()
- {
- PlatformDelegate.LoadRewarded();
- }
- public static void ShowRewarded()
- {
- PlatformDelegate.ShowRewarded();
- }
- public static bool IsRewardedReady()
+ public static void LoadRewarded(string rewardedAdUnitId)
{
- return PlatformDelegate.IsRewardedReady();
+ PlatformDelegate.LoadRewarded(rewardedAdUnitId);
}
-
- public static void NotifyAdLoadAttempt(string interstitialAdUnitId)
- {
- PlatformDelegate.NotifyAdLoadAttempt(interstitialAdUnitId);
- }
-
- public static void NotifyAdLoadSuccess(MeticaAd meticaAd)
+ public static void ShowRewarded(string rewardedAdUnitId)
{
- PlatformDelegate.NotifyAdLoadSuccess(meticaAd);
+ PlatformDelegate.ShowRewarded(rewardedAdUnitId);
}
-
- public static void NotifyAdLoadFailed(string adUnitId, string error)
- {
- PlatformDelegate.NotifyAdLoadFailed(adUnitId, error);
- }
-
- public static void NotifyAdShowSuccess(MeticaAd meticaAd)
+ public static bool IsRewardedReady(string rewardedAdUnitId)
{
- // Internally we use the NotifyAdRevenue call, but externally as to not
- // break API we use NotifyAdShowSuccess. Which is similar as both will tel you ad was shown.
- PlatformDelegate.NotifyAdRevenue(meticaAd);
+ return PlatformDelegate.IsRewardedReady(rewardedAdUnitId);
}
private static UnityPlayer.UnityPlayerDelegate GetUnityPlayerDelegate()
diff --git a/Runtime/ADS/MeticaAdsAssignmentStatus.cs b/Runtime/ADS/MeticaAdsAssignmentStatus.cs
index 2598553..318733f 100644
--- a/Runtime/ADS/MeticaAdsAssignmentStatus.cs
+++ b/Runtime/ADS/MeticaAdsAssignmentStatus.cs
@@ -1,9 +1,11 @@
namespace Metica.ADS
{
- public enum MeticaAdsAssignmentStatus
- {
- Normal,
- Holdout,
- HoldoutDueToError,
- }
+[System.Obsolete(
+ "Use MeticaUserGroup instead. This enum has been superseded by MeticaUserGroup which provides clearer trial/holdout assignment status.")]
+public enum MeticaAdsAssignmentStatus
+{
+ Normal,
+ Holdout,
+ HoldoutDueToError,
+}
}
diff --git a/Runtime/ADS/MeticaConfiguration.cs b/Runtime/ADS/MeticaConfiguration.cs
index a3beaf6..32e3e39 100644
--- a/Runtime/ADS/MeticaConfiguration.cs
+++ b/Runtime/ADS/MeticaConfiguration.cs
@@ -1,6 +1,33 @@
-namespace Metica.ADS
+using System.Collections.Generic;
+
+namespace Metica.ADS
{
-public class MeticaConfiguration
-{
-}
+ [System.Serializable]
+ public struct MeticaConfiguration
+ {
+ ///
+ /// Metica API Key
+ ///
+ public string ApiKey;
+ ///
+ /// Metica App ID
+ ///
+ public string AppId;
+ [System.Obsolete]
+ public string UserId;
+ [System.Obsolete]
+ public string Version;
+ public string BaseEndpoint;
+ ///
+ /// Allows adding custom API keys or other values.
+ /// TODO: https://linear.app/metica/issue/MET-4645/custom-additional-api-keys
+ ///
+ public List CustomKeys;
+
+ public struct KeyMap
+ {
+ public string Key;
+ public string Value;
+ }
+ }
}
diff --git a/Runtime/ADS/MeticaAdsInitializationResult.cs b/Runtime/ADS/MeticaInitializationResult.cs
similarity index 82%
rename from Runtime/ADS/MeticaAdsInitializationResult.cs
rename to Runtime/ADS/MeticaInitializationResult.cs
index f1bf6b5..6adaee7 100644
--- a/Runtime/ADS/MeticaAdsInitializationResult.cs
+++ b/Runtime/ADS/MeticaInitializationResult.cs
@@ -1,8 +1,10 @@
namespace Metica.ADS
{
- public class MeticaAdsInitializationResult
+ public class MeticaInitializationResult
{
- public MeticaAdsInitializationResult(MeticaAdsAssignmentStatus status)
+ public MeticaAdsAssignmentStatus Status { get; }
+
+ public MeticaInitializationResult(MeticaAdsAssignmentStatus status)
{
Status = status;
}
@@ -21,7 +23,5 @@ public bool IsMeticaAdsEnabled
return false;
}
}
-
- public MeticaAdsAssignmentStatus Status { get; }
}
}
diff --git a/Runtime/ADS/MeticaAdsInitializationResult.cs.meta b/Runtime/ADS/MeticaInitializationResult.cs.meta
similarity index 100%
rename from Runtime/ADS/MeticaAdsInitializationResult.cs.meta
rename to Runtime/ADS/MeticaInitializationResult.cs.meta
diff --git a/Runtime/ADS/MeticaSmartFloors.cs b/Runtime/ADS/MeticaSmartFloors.cs
new file mode 100644
index 0000000..aee3bc0
--- /dev/null
+++ b/Runtime/ADS/MeticaSmartFloors.cs
@@ -0,0 +1,16 @@
+using UnityEngine;
+
+namespace Metica.ADS
+{
+public class MeticaSmartFloors
+{
+ public MeticaUserGroup userGroup { get; private set; }
+ public bool isSuccess { get; private set; }
+
+ public MeticaSmartFloors(MeticaUserGroup userGroup, bool isSuccess)
+ {
+ this.userGroup = userGroup;
+ this.isSuccess = isSuccess;
+ }
+}
+}
diff --git a/Runtime/ADS/MeticaSmartFloors.cs.meta b/Runtime/ADS/MeticaSmartFloors.cs.meta
new file mode 100644
index 0000000..2bab9fa
--- /dev/null
+++ b/Runtime/ADS/MeticaSmartFloors.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 0ab180902e6e47ab93b38890639fec66
+timeCreated: 1760174356
\ No newline at end of file
diff --git a/Runtime/ADS/MeticaUserGroup.cs b/Runtime/ADS/MeticaUserGroup.cs
new file mode 100644
index 0000000..e5e0f8d
--- /dev/null
+++ b/Runtime/ADS/MeticaUserGroup.cs
@@ -0,0 +1,8 @@
+namespace Metica.ADS
+{
+public enum MeticaUserGroup
+{
+ TRIAL,
+ HOLDOUT,
+}
+}
diff --git a/Runtime/ADS/MeticaUserGroup.cs.meta b/Runtime/ADS/MeticaUserGroup.cs.meta
new file mode 100644
index 0000000..bcf1a9e
--- /dev/null
+++ b/Runtime/ADS/MeticaUserGroup.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 2f2a3c87b4ad4df1b2a0a94a8cb04ae8
+timeCreated: 1760174264
\ No newline at end of file
diff --git a/Runtime/ADS/Platform/Android/AndroidDelegate.cs b/Runtime/ADS/Platform/Android/AndroidDelegate.cs
index 6d4f3d8..bc76433 100644
--- a/Runtime/ADS/Platform/Android/AndroidDelegate.cs
+++ b/Runtime/ADS/Platform/Android/AndroidDelegate.cs
@@ -10,23 +10,21 @@ namespace Metica.ADS.Android
{
internal class AndroidDelegate : PlatformDelegate
{
- public AndroidDelegate(AndroidJavaClass unityBridgeClass, AndroidJavaClass meticaAdsExternalTrackerClass)
+ public AndroidDelegate(AndroidJavaClass unityBridgeClass)
{
_unityBridgeAndroidClass = unityBridgeClass;
- _meticaAdsExternalTrackerAndroidClass = meticaAdsExternalTrackerClass;
}
private const string TAG = MeticaAds.TAG;
private readonly AndroidJavaClass _unityBridgeAndroidClass;
- private readonly AndroidJavaClass _meticaAdsExternalTrackerAndroidClass;
// Events for banner ad lifecycle callbacks
public event Action BannerAdLoadSuccess;
public event Action BannerAdLoadFailed;
public event Action BannerAdClicked;
public event Action BannerAdRevenuePaid;
-
+
// Events for interstitial ad lifecycle callbacks
public event Action InterstitialAdLoadSuccess;
public event Action InterstitialAdLoadFailed;
@@ -53,13 +51,19 @@ public void SetLogEnabled(bool logEnabled)
_unityBridgeAndroidClass.CallStatic("setLogEnabled", logEnabled);
}
- public Task InitializeAsync(string apiKey, string appId, string userId, string version, string baseEndpoint,
+ public Task InitializeAsync(string apiKey, string appId, string userId, string version,
+ string baseEndpoint,
MeticaConfiguration configuration)
{
- var tcs = new TaskCompletionSource();
+ var tcs = new TaskCompletionSource();
+
+ var callback = new InitCallbackProxy(tcs);
+
+ // TODO: pass it in the function
+ const string applovinSdkKey =
+ "CZ_XxS0v1pDXVdV2yDXaxO4dOV8849QwTq7iDFlGLsJZngU95AEyaq2z8lF0GRlSvdknWDpTDp1GmprFC1FiJ1";
- var callback = new InitializeCallbackProxy(tcs);
- _unityBridgeAndroidClass.CallStatic("initialize", apiKey, appId, userId, callback);
+ _unityBridgeAndroidClass.CallStatic("initialize", apiKey, appId, applovinSdkKey, userId, callback);
return tcs.Task;
}
@@ -81,12 +85,13 @@ public void CreateBanner(string adUnitId, MeticaBannerPosition position)
MeticaBannerPosition.Top => 0,
_ => 0,
};
-
-
+
+
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android createBanner method");
_unityBridgeAndroidClass.CallStatic("createBanner", adUnitId, yPosition, callback);
MeticaAds.Log.LogDebug(() => $"{TAG} Android createBanner method called");
}
+
public void ShowBanner(string adUnitId)
{
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android showBanner method");
@@ -107,9 +112,9 @@ public void DestroyBanner(string adUnitId)
_unityBridgeAndroidClass.CallStatic("destroyBanner", adUnitId);
MeticaAds.Log.LogDebug(() => $"{TAG} Android destroyBanner method called");
}
-
+
// Interstitial methods
- public void LoadInterstitial()
+ public void LoadInterstitial(string interstitialAdUnitId)
{
var callback = new LoadCallbackProxy();
@@ -118,11 +123,11 @@ public void LoadInterstitial()
callback.AdLoadFailed += (error) => InterstitialAdLoadFailed?.Invoke(error);
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android loadInterstitial method");
- _unityBridgeAndroidClass.CallStatic("loadInterstitial", callback);
+ _unityBridgeAndroidClass.CallStatic("loadInterstitial", interstitialAdUnitId, callback);
MeticaAds.Log.LogDebug(() => $"{TAG} Android loadInterstitial method called");
}
- public void ShowInterstitial()
+ public void ShowInterstitial(string interstitialAdUnitId)
{
var callback = new ShowCallbackProxy();
@@ -134,17 +139,17 @@ public void ShowInterstitial()
callback.AdRevenuePaid += (meticaAd) => InterstitialAdRevenuePaid?.Invoke(meticaAd);
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android showInterstitial method");
- _unityBridgeAndroidClass.CallStatic("showInterstitial", callback);
+ _unityBridgeAndroidClass.CallStatic("showInterstitial", interstitialAdUnitId, callback);
MeticaAds.Log.LogDebug(() => $"{TAG} Android showInterstitial method called");
}
- public bool IsInterstitialReady()
+ public bool IsInterstitialReady(string interstitialAdUnitId)
{
- return _unityBridgeAndroidClass.CallStatic("isInterstitialReady");
+ return _unityBridgeAndroidClass.CallStatic("isInterstitialReady", interstitialAdUnitId);
}
// Rewarded methods
- public void LoadRewarded()
+ public void LoadRewarded(string rewardedAdUnitId)
{
var callback = new LoadCallbackProxy();
@@ -153,11 +158,11 @@ public void LoadRewarded()
callback.AdLoadFailed += (error) => RewardedAdLoadFailed?.Invoke(error);
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android loadRewarded method");
- _unityBridgeAndroidClass.CallStatic("loadRewarded", callback);
+ _unityBridgeAndroidClass.CallStatic("loadRewarded", rewardedAdUnitId, callback);
MeticaAds.Log.LogDebug(() => $"{TAG} Android loadRewarded method called");
}
- public void ShowRewarded()
+ public void ShowRewarded(string rewardedAdUnitId)
{
var callback = new ShowCallbackProxy();
@@ -170,46 +175,13 @@ public void ShowRewarded()
callback.AdRevenuePaid += (meticaAd) => RewardedAdRevenuePaid?.Invoke(meticaAd);
MeticaAds.Log.LogDebug(() => $"{TAG} About to call Android showRewarded method");
- _unityBridgeAndroidClass.CallStatic("showRewarded", callback);
+ _unityBridgeAndroidClass.CallStatic("showRewarded", rewardedAdUnitId, callback);
MeticaAds.Log.LogDebug(() => $"{TAG} Android showRewarded method called");
}
- public bool IsRewardedReady()
- {
- return _unityBridgeAndroidClass.CallStatic("isRewardedReady");
- }
-
- // Notification methods
- public void NotifyAdLoadAttempt(string adUnitId)
+ public bool IsRewardedReady(string rewardedAdUnitId)
{
- MeticaAds.Log.LogDebug(() => $"{TAG} NotifyAdLoadAttempt called for adUnitId: {adUnitId}");
- _meticaAdsExternalTrackerAndroidClass.CallStatic("notifyAdLoadAttempt", adUnitId);
- }
-
- public void NotifyAdLoadSuccess(MeticaAd meticaAd)
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} NotifyAdLoadSuccess called for adUnitId: {meticaAd.adUnitId}");
-
- using (var meticaAdAndroid = meticaAd.ToAndroidJavaObject())
- {
- _meticaAdsExternalTrackerAndroidClass.CallStatic("notifyAdLoadSuccess", meticaAdAndroid);
- }
- }
-
- public void NotifyAdLoadFailed(string adUnitId, string error)
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} NotifyAdLoadFailed called for adUnitId: {adUnitId}, error: {error}");
- _meticaAdsExternalTrackerAndroidClass.CallStatic("notifyAdLoadFailed", adUnitId, error);
- }
-
- public void NotifyAdRevenue(MeticaAd meticaAd)
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} NotifyAdRevenue called for adUnitId: {meticaAd.adUnitId}");
-
- using (var meticaAdAndroid = meticaAd.ToAndroidJavaObject())
- {
- _meticaAdsExternalTrackerAndroidClass.CallStatic("notifyAdRevenue", meticaAdAndroid);
- }
+ return _unityBridgeAndroidClass.CallStatic("isRewardedReady", rewardedAdUnitId);
}
}
}
diff --git a/Runtime/ADS/Platform/Android/AndroidJavaObjectExtensions.cs b/Runtime/ADS/Platform/Android/AndroidJavaObjectExtensions.cs
index a01ab72..1346e80 100644
--- a/Runtime/ADS/Platform/Android/AndroidJavaObjectExtensions.cs
+++ b/Runtime/ADS/Platform/Android/AndroidJavaObjectExtensions.cs
@@ -1,61 +1,51 @@
-// AndroidJavaObjectExtensions.cs
-
-using Metica.ADS.Android;
using UnityEngine;
namespace Metica.ADS
-{
-///
-/// Extension methods for converting AndroidJavaObject instances to C# objects.
-///
-public static class AndroidJavaObjectExtensions
{
///
- /// Converts an AndroidJavaObject representing a MeticaAd to a C# MeticaAd object.
+ /// Extension methods for converting AndroidJavaObject instances to C# objects.
///
- /// The AndroidJavaObject containing MeticaAd data from the Android side
- /// A new MeticaAd instance with data extracted from the AndroidJavaObject
- ///
- /// This method extracts the following properties from the AndroidJavaObject:
- /// - adUnitId: The unique identifier for the ad unit
- /// - revenue: The revenue value (non-nullable)
- /// - networkName: The name of the ad network (nullable)
- /// - placementTag: The placement tag for the ad (nullable)
- /// - adFormat: The format type of the ad (nullable)
- /// - creativeId: The creative identifier for the ad (nullable)
- ///
- ///
- /// Thrown if javaObject is null or if required properties are missing
- ///
- public static MeticaAd ToMeticaAd(this AndroidJavaObject javaObject)
+ public static class AndroidJavaObjectExtensions
{
- string adUnitId = javaObject.Get("adUnitId");
- double revenue = javaObject.Get("revenue");
- string networkName = javaObject.Get("networkName");
- string placementTag = javaObject.Get("placementTag");
- string adFormat = javaObject.Get("adFormat");
- string creativeId = javaObject.Get("creativeId");
- long latency = javaObject.Get("latency");
+ ///
+ /// Converts an AndroidJavaObject representing a MeticaAd to a C# MeticaAd object.
+ ///
+ /// The AndroidJavaObject containing MeticaAd data from the Android side
+ /// A new MeticaAd instance with data extracted from the AndroidJavaObject
+ ///
+ /// This method extracts the following properties from the AndroidJavaObject:
+ /// - adUnitId: The unique identifier for the ad unit
+ /// - revenue: The revenue value (non-nullable)
+ /// - networkName: The name of the ad network (nullable)
+ /// - placementTag: The placement tag for the ad (nullable)
+ /// - adFormat: The format type of the ad (nullable)
+ /// - creativeId: The creative identifier for the ad (nullable)
+ ///
+ ///
+ /// Thrown if javaObject is null or if required properties are missing
+ ///
+ public static MeticaAd ToMeticaAd(this AndroidJavaObject javaObject)
+ {
+ string adUnitId = javaObject.Get("adUnitId");
+ double revenue = javaObject.Get("revenue");
+ string networkName = javaObject.Get("networkName");
+ string placementTag = javaObject.Get("placementTag");
+ string adFormat = javaObject.Get("adFormat");
+ string creativeId = javaObject.Get("creativeId");
+ long latency = javaObject.Get("latency");
- return new MeticaAd(adUnitId, revenue, networkName, placementTag, adFormat, creativeId, latency);
- }
-
- ///
- /// Converts a MeticaAd object to an AndroidJavaObject for Unity-Android interop.
- ///
- /// The MeticaAd object to convert
- /// AndroidJavaObject representing the MeticaAd on the Android side
- public static AndroidJavaObject ToAndroidJavaObject(this MeticaAd meticaAd)
- {
- return AndroidUnityBridge.UnityBridgeClass.CallStatic("createMeticaAd",
- meticaAd.adUnitId,
- meticaAd.revenue,
- meticaAd.networkName,
- meticaAd.placementTag,
- meticaAd.adFormat,
- meticaAd.creativeId,
- meticaAd.latency
- );
+ return new MeticaAd(adUnitId, revenue, networkName, placementTag, adFormat, creativeId, latency);
+ }
+
+ public static MeticaSmartFloors ToMeticaSmartFloors(this AndroidJavaObject javaObject)
+ {
+ var userGroupJavaObject = javaObject.Call("getUserGroup");
+ var userGroupName = userGroupJavaObject.Call("name");
+ var userGroup = (MeticaUserGroup)System.Enum.Parse(typeof(MeticaUserGroup), userGroupName);
+
+ var isSuccess = javaObject.Call("isSuccess");
+
+ return new MeticaSmartFloors(userGroup, isSuccess);
+ }
}
}
-}
diff --git a/Runtime/ADS/Platform/Android/AndroidUnityBridge.cs b/Runtime/ADS/Platform/Android/AndroidUnityBridge.cs
index bde71da..ccc05d2 100644
--- a/Runtime/ADS/Platform/Android/AndroidUnityBridge.cs
+++ b/Runtime/ADS/Platform/Android/AndroidUnityBridge.cs
@@ -2,12 +2,10 @@
namespace Metica.ADS
{
-internal static class AndroidUnityBridge
-{
- public static readonly AndroidJavaClass UnityBridgeClass =
- new("com.metica.unity_bridge.UnityBridge");
+ internal static class AndroidUnityBridge
+ {
+ public static readonly AndroidJavaClass UnityBridgeClass =
+ new("com.metica.unity_bridge.UnityBridge");
- public static readonly AndroidJavaClass MeticaAdsExternalTrackerClass =
- new("com.metica.ads.MeticaAdsExternalTracker");
-}
+ }
}
diff --git a/Runtime/ADS/Platform/Android/BannerCallbackProxy.cs b/Runtime/ADS/Platform/Android/BannerCallbackProxy.cs
index 311e5ed..0ecd9cb 100644
--- a/Runtime/ADS/Platform/Android/BannerCallbackProxy.cs
+++ b/Runtime/ADS/Platform/Android/BannerCallbackProxy.cs
@@ -11,7 +11,7 @@ public class BannerCallbackProxy : AndroidJavaProxy
public event Action AdLoadFailed;
public event Action AdClicked;
public event Action AdRevenuePaid;
-
+
public BannerCallbackProxy()
: base("com.metica.ads.MeticaAdsBannerCallback")
{
diff --git a/Runtime/ADS/Platform/Android/InitCallbackProxy.cs b/Runtime/ADS/Platform/Android/InitCallbackProxy.cs
new file mode 100644
index 0000000..fe72272
--- /dev/null
+++ b/Runtime/ADS/Platform/Android/InitCallbackProxy.cs
@@ -0,0 +1,47 @@
+// InitializeCallbackProxy.cs
+
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+using UnityEngine;
+
+namespace Metica.ADS
+{
+[SuppressMessage("ReSharper", "InconsistentNaming")]
+public class InitCallbackProxy : AndroidJavaProxy
+{
+ private const string TAG = MeticaAds.TAG;
+ private readonly TaskCompletionSource _tcs;
+
+ public InitCallbackProxy(TaskCompletionSource tcs)
+ : base("com.metica.MeticaInitCallback")
+ {
+ MeticaAds.Log.LogDebug(() => $"{TAG} MeticaAdsInitCallback created");
+ _tcs = tcs;
+ }
+
+ // Called from Android when initialization succeeds
+ public void onInit(AndroidJavaObject initResponseJavaObject)
+ {
+ MeticaAds.Log.LogDebug(() => $"{TAG} InitCallbackProxy onInit");
+ var smartFloorsJavaObject = initResponseJavaObject.Call("getSmartFloors");
+ var smartFloors = smartFloorsJavaObject.ToMeticaSmartFloors();
+
+ MeticaAds.Log.LogDebug(() => $"{TAG} InitCallbackProxy smartFloorsObj = {smartFloors}");
+
+ if (smartFloors.userGroup == MeticaUserGroup.TRIAL)
+ {
+ _tcs.SetResult(
+ new MeticaInitializationResult(MeticaAdsAssignmentStatus.Normal)
+ );
+ }
+ else
+ {
+ _tcs.SetResult(
+ smartFloors.isSuccess
+ ? new MeticaInitializationResult(MeticaAdsAssignmentStatus.Holdout)
+ : new MeticaInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
+ );
+ }
+ }
+}
+}
diff --git a/Runtime/ADS/Platform/Android/InitializeCallbackProxy.cs.meta b/Runtime/ADS/Platform/Android/InitCallbackProxy.cs.meta
similarity index 100%
rename from Runtime/ADS/Platform/Android/InitializeCallbackProxy.cs.meta
rename to Runtime/ADS/Platform/Android/InitCallbackProxy.cs.meta
diff --git a/Runtime/ADS/Platform/Android/InitResponseProxy.cs b/Runtime/ADS/Platform/Android/InitResponseProxy.cs
new file mode 100644
index 0000000..fcb58a6
--- /dev/null
+++ b/Runtime/ADS/Platform/Android/InitResponseProxy.cs
@@ -0,0 +1,19 @@
+// LoadCallbackProxy.cs
+
+using System;
+using UnityEngine;
+
+namespace Metica.ADS
+{
+public class InitResponseProxy
+{
+ private const string TAG = MeticaAds.TAG;
+
+ public InitResponseProxy(AndroidJavaObject javaObject)
+ {
+ MeticaAds.Log.LogDebug(() => $"{TAG} InitResponseProxy created");
+ var smartFloorsObj = javaObject.Get("smartFloors");
+ MeticaAds.Log.LogDebug(() => $"{TAG} InitResponseProxy smartFloorsObj = {smartFloorsObj}");
+ }
+}
+}
diff --git a/Runtime/ADS/Platform/Android/InitResponseProxy.cs.meta b/Runtime/ADS/Platform/Android/InitResponseProxy.cs.meta
new file mode 100644
index 0000000..65df73a
--- /dev/null
+++ b/Runtime/ADS/Platform/Android/InitResponseProxy.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 00eaead4730e4e0887d6a40118851f65
+timeCreated: 1760172387
\ No newline at end of file
diff --git a/Runtime/ADS/Platform/Android/InitializeCallbackProxy.cs b/Runtime/ADS/Platform/Android/InitializeCallbackProxy.cs
deleted file mode 100644
index 2d5f8b5..0000000
--- a/Runtime/ADS/Platform/Android/InitializeCallbackProxy.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Threading.Tasks;
-using UnityEngine;
-
-namespace Metica.ADS
-{
- [SuppressMessage("ReSharper", "InconsistentNaming")]
- public class InitializeCallbackProxy : AndroidJavaProxy
- {
- private const string TAG = MeticaAds.TAG;
- private readonly TaskCompletionSource _tcs;
-
- public InitializeCallbackProxy(TaskCompletionSource tcs)
- : base("com.metica.MeticaInitCallback")
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} MeticaAdsInitCallback created");
- _tcs = tcs;
- }
-
- // Called from Android when initialization succeeds
- public void onInitialized(bool adsEnabled)
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} onInitialized: {adsEnabled}");
- if (adsEnabled)
- {
- _tcs.SetResult(
- new MeticaAdsInitializationResult(MeticaAdsAssignmentStatus.Normal)
- );
- }
- else
- {
- _tcs.SetResult(
- new MeticaAdsInitializationResult(MeticaAdsAssignmentStatus.Holdout)
- );
- }
- }
-
- // Called from Android when initialization fails
- public void onFailed(string reason)
- {
- MeticaAds.Log.LogDebug(() => $"{TAG} onFailed: {reason}");
- _tcs.SetResult(
- new MeticaAdsInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
- );
- }
- }
-}
diff --git a/Runtime/ADS/Platform/Android/ShowCallbackProxy.cs b/Runtime/ADS/Platform/Android/ShowCallbackProxy.cs
index 2a13574..66dc4e5 100644
--- a/Runtime/ADS/Platform/Android/ShowCallbackProxy.cs
+++ b/Runtime/ADS/Platform/Android/ShowCallbackProxy.cs
@@ -1,5 +1,3 @@
-// ShowCallbackProxy.cs
-
using System;
using UnityEngine;
diff --git a/Runtime/ADS/Platform/IOS/IOSDelegate.cs b/Runtime/ADS/Platform/IOS/IOSDelegate.cs
index 4322a86..f599647 100644
--- a/Runtime/ADS/Platform/IOS/IOSDelegate.cs
+++ b/Runtime/ADS/Platform/IOS/IOSDelegate.cs
@@ -56,64 +56,44 @@ public void DestroyBanner(string adUnitId)
{
}
- public Task InitializeAsync(string apiKey, string appId, string userId, string version, string baseEndpoint,
+ public Task InitializeAsync(string apiKey, string appId, string userId, string version, string baseEndpoint,
MeticaConfiguration configuration)
{
- var tcs = new TaskCompletionSource();
+ var tcs = new TaskCompletionSource();
tcs.SetResult(
- new MeticaAdsInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
+ new MeticaInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
);
return tcs.Task;
}
// Interstitial methods
- public void LoadInterstitial()
+ public void LoadInterstitial(string interstitialAdUnitId)
{
}
- public void ShowInterstitial()
+ public void ShowInterstitial(string interstitialAdUnitId)
{
}
- public bool IsInterstitialReady()
+ public bool IsInterstitialReady(string interstitialAdUnitId)
{
return false;
}
// Rewarded methods
- public void LoadRewarded()
+ public void LoadRewarded(string rewardedAdUnitId)
{
}
- public void ShowRewarded()
+ public void ShowRewarded(string rewardedAdUnitId)
{
}
- public bool IsRewardedReady()
+ public bool IsRewardedReady(string rewardedAdUnitId)
{
return false;
}
- // Notification methods
- public void NotifyAdLoadAttempt(string adUnitId)
- {
- // TODO: Implement iOS native call
- }
-
- public void NotifyAdLoadSuccess(MeticaAd meticaAd)
- {
- // TODO: Implement iOS native call
- }
-
- public void NotifyAdLoadFailed(string adUnitId, string error)
- {
- // TODO: Implement iOS native call
- }
-
- public void NotifyAdRevenue(MeticaAd meticaAd)
- {
- // TODO: Implement iOS native call
- }
}
}
diff --git a/Runtime/ADS/Platform/PlatformDelegate.cs b/Runtime/ADS/Platform/PlatformDelegate.cs
index 0bdf3ef..a74165d 100644
--- a/Runtime/ADS/Platform/PlatformDelegate.cs
+++ b/Runtime/ADS/Platform/PlatformDelegate.cs
@@ -32,7 +32,7 @@ internal interface PlatformDelegate
public event Action RewardedAdRewarded;
public event Action RewardedAdRevenuePaid;
- Task InitializeAsync(
+ Task InitializeAsync(
string apiKey,
string appId,
string userId,
@@ -49,19 +49,13 @@ MeticaConfiguration configuration
void DestroyBanner(string adUnitId);
// Interstitial methods
- void LoadInterstitial();
- void ShowInterstitial();
- bool IsInterstitialReady();
+ void LoadInterstitial(string interstitialAdUnitId);
+ void ShowInterstitial(string interstitialAdUnitId);
+ bool IsInterstitialReady(string interstitialAdUnitId);
// Rewarded methods
- void LoadRewarded();
- void ShowRewarded();
- bool IsRewardedReady();
-
- // Notification methods
- void NotifyAdLoadAttempt(string adUnitId);
- void NotifyAdLoadSuccess(MeticaAd meticaAd);
- void NotifyAdLoadFailed(string adUnitId, string error);
- void NotifyAdRevenue(MeticaAd meticaAd);
+ void LoadRewarded(string rewardedAdUnitId);
+ void ShowRewarded(string rewardedAdUnitId);
+ bool IsRewardedReady(string rewardedAdUnitId);
}
}
diff --git a/Runtime/ADS/Platform/UnityPlayer/UnityPlayerDelegate.cs b/Runtime/ADS/Platform/UnityPlayer/UnityPlayerDelegate.cs
index 501a580..425e931 100644
--- a/Runtime/ADS/Platform/UnityPlayer/UnityPlayerDelegate.cs
+++ b/Runtime/ADS/Platform/UnityPlayer/UnityPlayerDelegate.cs
@@ -27,13 +27,13 @@ internal class UnityPlayerDelegate : PlatformDelegate
public event Action RewardedAdRewarded;
public event Action RewardedAdRevenuePaid;
- public Task InitializeAsync(string apiKey, string appId, string userId, string version, string baseEndpoint,
+ public Task InitializeAsync(string apiKey, string appId, string userId, string version, string baseEndpoint,
MeticaConfiguration meticaConfiguration)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock initialization - always returns HoldoutDueToError");
- var tcs = new TaskCompletionSource();
+ var tcs = new TaskCompletionSource();
tcs.SetResult(
- new MeticaAdsInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
+ new MeticaInitializationResult(MeticaAdsAssignmentStatus.HoldoutDueToError)
);
return tcs.Task;
}
@@ -64,56 +64,36 @@ public void DestroyBanner(string adUnitId)
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock DestroyBanner called");
}
- public void LoadInterstitial()
+ public void LoadInterstitial(string interstitialAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock LoadInterstitial called");
}
- public void ShowInterstitial()
+ public void ShowInterstitial(string interstitialAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock ShowInterstitial called");
}
- public bool IsInterstitialReady()
+ public bool IsInterstitialReady(string interstitialAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock IsInterstitialReady - always returns false");
return false;
}
- public void LoadRewarded()
+ public void LoadRewarded(string rewardedAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock LoadRewarded called");
}
- public void ShowRewarded()
+ public void ShowRewarded(string rewardedAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock ShowRewarded called");
}
- public bool IsRewardedReady()
+ public bool IsRewardedReady(string rewardedAdUnitId)
{
MeticaAds.Log.LogDebug(() => "[MeticaAds Unity] Mock IsRewardedReady - always returns false");
return false;
}
- // Notification methods
- public void NotifyAdLoadAttempt(string adUnitId)
- {
- MeticaAds.Log.LogDebug(() => $"[MeticaAds Unity] Mock NotifyAdLoadAttempt called for adUnitId: {adUnitId}");
- }
-
- public void NotifyAdLoadSuccess(MeticaAd meticaAd)
- {
- MeticaAds.Log.LogDebug(() => $"[MeticaAds Unity] Mock NotifyAdLoadSuccess called for adUnitId: {meticaAd.adUnitId}");
- }
-
- public void NotifyAdLoadFailed(string adUnitId, string error)
- {
- MeticaAds.Log.LogDebug(() => $"[MeticaAds Unity] Mock NotifyAdLoadFailed called for adUnitId: {adUnitId}, error: {error}");
- }
-
- public void NotifyAdRevenue(MeticaAd meticaAd)
- {
- MeticaAds.Log.LogDebug(() => $"[MeticaAds Unity] Mock NotifyAdShowSuccess called for adUnitId: {meticaAd.adUnitId}");
- }
}
}
diff --git a/Runtime/Core/Registry.cs b/Runtime/Core/Registry.cs
index 11641d5..12ab700 100644
--- a/Runtime/Core/Registry.cs
+++ b/Runtime/Core/Registry.cs
@@ -29,6 +29,12 @@ public static Registry Instance
}
}
+ ///
+ /// Registers an implementation for the type .
+ /// Replaces the previous implementation if present.
+ ///
+ /// An interface type
+ /// An instance that implements .
public static void Register(T implementation)
{
Assert.IsTrue(typeof(T).IsInterface);
@@ -36,6 +42,42 @@ public static void Register(T implementation)
Instance.RegisterType(implementation);
}
+ ///
+ /// Like but does not replace the current implementation.
+ ///
+ /// An interface type
+ /// An instance that implements .
+ public static void RegisterIfNull(T implementation)
+ {
+ Assert.IsTrue(typeof(T).IsInterface);
+
+ if (Instance.ResolveType() == null)
+ {
+ Instance.RegisterType(implementation);
+ }
+ }
+
+ ///
+ /// Registers an implementation for the type .
+ /// Fails if an implementation for the type is already registered.
+ ///
+ /// An interface type
+ /// An instance that implements .
+ ///
+ // ///
+ // public static void TryRegister(T implementation)
+ // {
+ // if (Instance.ResolveType() != null)
+ // {
+ // throw new InvalidOperationException($"Type {nameof(T)} is already registered with implementation {implementation.GetType().Name}");
+ // }
+ // else
+ // {
+ // Register(implementation);
+ // }
+ // }
+
+
public static T Resolve()
{
Assert.IsTrue(typeof(T).IsInterface);
@@ -48,10 +90,7 @@ private void RegisterType(T implementation)
Assert.IsTrue(typeof(T).IsInterface);
var serviceType = typeof(T);
- if (!services.ContainsKey(serviceType))
- {
- services.Add(serviceType, implementation);
- }
+ services[serviceType] = implementation;
}
private T ResolveType()
@@ -65,7 +104,7 @@ private T ResolveType()
}
else
{
- throw new InvalidOperationException($"Service of type {serviceType} is not registered.");
+ return default;
}
}
diff --git a/Runtime/SDK/EventManager.cs b/Runtime/SDK/EventManager.cs
index deffc65..29536c1 100644
--- a/Runtime/SDK/EventManager.cs
+++ b/Runtime/SDK/EventManager.cs
@@ -50,7 +50,7 @@ internal class EventManager : EndpointManager
private readonly IMeticaAttributesProvider _meticaAttributesProvider;
private readonly ITimeSource _timeSource = new SystemDateTimeSource();
- public const uint DefaultEventQueueCountTrigger = 64; // Rename to DefaultQueueFlushCountTrigger
+ public const uint DefaultQueueFlushCountTrigger = 32;
private const uint DefaultQueueFlushTimeoutSecondsTrigger = 10;
private readonly uint _eventQueueCountTrigger;
private long _lastEventDispatchUnixTime = 0;
@@ -61,7 +61,7 @@ public EventManager(
IHttpService httpService,
string endpoint,
IMeticaAttributesProvider meticaAttributesProvider,
- uint eventQueueCountTrigger = DefaultEventQueueCountTrigger
+ uint eventQueueCountTrigger = DefaultQueueFlushCountTrigger
) : base(httpService, endpoint)
{
_meticaAttributesProvider = meticaAttributesProvider;
diff --git a/Runtime/SDK/ISdkConfigProvider.cs b/Runtime/SDK/ISdkConfigProvider.cs
index 6de327e..f19dd1d 100644
--- a/Runtime/SDK/ISdkConfigProvider.cs
+++ b/Runtime/SDK/ISdkConfigProvider.cs
@@ -1,7 +1,9 @@
+using Metica.ADS;
+
namespace Metica.SDK
{
- public interface ISdkConfigProvider
+ public interface IMeticaConfigProvider
{
- public SdkConfig SdkConfig { get; }
+ public MeticaConfiguration Config { get; }
}
}
diff --git a/Runtime/SDK/Metica.SDK.asmdef b/Runtime/SDK/Metica.SDK.asmdef
index 01001bc..6359553 100644
--- a/Runtime/SDK/Metica.SDK.asmdef
+++ b/Runtime/SDK/Metica.SDK.asmdef
@@ -3,7 +3,8 @@
"rootNamespace": "",
"references": [
"GUID:338a946abe1644d408adf5afa3f9bf49",
- "GUID:cae81f611ee505e4a805f6867af6cf27"
+ "GUID:cae81f611ee505e4a805f6867af6cf27",
+ "GUID:5297a986a6e349da9a62d3434a3be1d9"
],
"includePlatforms": [],
"excludePlatforms": [],
diff --git a/Runtime/SDK/MeticaSdk.cs b/Runtime/SDK/MeticaSdk.cs
index 946942c..7d3c21f 100644
--- a/Runtime/SDK/MeticaSdk.cs
+++ b/Runtime/SDK/MeticaSdk.cs
@@ -1,275 +1,342 @@
-using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Metica.Core;
using Metica.Network;
+using Metica.Core;
using Metica.SDK.Model;
+using Metica.SDK.Unity;
+using Metica.ADS;
namespace Metica.SDK
{
- public interface IMeticaSdk : IAsyncDisposable
+ public class MeticaSdk
{
- Task GetConfigsAsync(List configKeys = null, Dictionary userData = null);
- [Obsolete]
- Task GetConfigsAsync(List configKeys, Dictionary userData, DeviceInfo deviceInfo);
- Task GetOffersAsync(string[] placements, Dictionary userData = null);
- [Obsolete]
- Task GetOffersAsync(string[] placements, Dictionary userData, DeviceInfo deviceInfo);
- void LogAdRevenueEvent(string placement, string type, string source, string currencyCode, double totalAmount, Dictionary customPayload = null);
- void LogCustomEvent(string customEventType, Dictionary customPayload = null);
- void LogInstallEvent(Dictionary customPayload = null);
- void LogLoginEvent(Dictionary customPayload = null);
- void LogOfferImpressionEvent(string placementId, string offerId, Dictionary customPayload = null);
- void LogOfferImpressionEventWithProductId(string productId, Dictionary customPayload = null);
- void LogOfferInteractionEvent(string placementId, string offerId, string interactionType, Dictionary customPayload = null);
- void LogOfferInteractionEventWithProductId(string productId, string interactionType, Dictionary customPayload = null);
- void LogOfferPurchaseEvent(string placementId, string offerId, string currencyCode, double totalAmount, Dictionary customPayload = null);
- void LogOfferPurchaseEventWithProductId(string productId, string currencyCode, double totalAmount, Dictionary customPayload = null);
- void LogFullStateUserUpdateEvent(Dictionary fullUserStateAttributes, Dictionary customPayload = null);
- void LogPartialStateUserUpdateEvent(Dictionary partialUserStateAttributes, Dictionary customPayload = null);
- void RequestDispatchEvents();
- }
+ static MeticaSdk()
+ {
+ Registry.RegisterIfNull(new DeviceInfoProvider());
+ Registry.RegisterIfNull(new MeticaLogger(LogLevel.Error));
+ }
- public class MeticaSdk : IMeticaSdk
- {
#region Fields
- public static IMeticaSdk SDK { get => Registry.Resolve(); }
+ private static MeticaSdk Sdk { get; set; } = null;
- public static string Version { get => "1.13.5"; }
+ public static string Version { get => "2.0.0-beta1"; }
- public static string CurrentUserId { get; set; }
+ public static string UserId { get; set; } // TODO: set should become private and require a reinitialization to cheange user id
public static string ApiKey { get; private set; }
public static string AppId { get; private set; }
public static string BaseEndpoint { get; private set; }
+ // TODO: remove apploving key from here in favour of
+ // more configurability considering possible additions of other ad providers.
+ public static string ApplovinKey { get; private set; }
- private readonly SdkConfig _sdkConfig;
private readonly IHttpService _http;
private readonly OfferManager _offerManager;
private readonly ConfigManager _configManager;
private readonly EventManager _eventManager;
- private SdkConfig Config { get => _sdkConfig; } // alias for above
+ public static bool IsMeticaAdsEnabled { get; private set; }
#endregion Fields
+ #region Methods
+
+ public static void SetLogEnabled(bool logEnabled)
+ {
+ Registry.Register(new MeticaLogger(LogLevel.Debug));
+ MeticaAds.SetLogEnabled(logEnabled);
+ }
///
- /// Utility, (Unity specific) method that should not be used directly.
+ /// Utility, (Unity specific) method that should not be used directly.
/// Resets static properties to null.
///
public static void ResetStaticFields()
{
- CurrentUserId = null;
+ UserId = null;
ApiKey = null;
AppId = null;
BaseEndpoint = null;
}
- ///
- /// Metica SDK, engine and platform independent, control room.
- ///
- /// Metica SDK configuration object.
- ///
- /// ROADMAP
- /// - Swap inline strings like "purchase" with constants.
- ///
- public MeticaSdk(SdkConfig config)
+ private static bool CheckConfig(MeticaConfiguration config)
{
- _sdkConfig = config;
-
- if(string.IsNullOrEmpty(_sdkConfig.apiKey) || string.IsNullOrEmpty(_sdkConfig.appId) || string.IsNullOrEmpty(config.baseEndpoint))
+ if (string.IsNullOrEmpty(config.ApiKey) || string.IsNullOrEmpty(config.AppId) || string.IsNullOrEmpty(config.BaseEndpoint))
{
Log.Error(() => "The given SDK configuration is not valid. Please make sure all fields are filled.");
- return;
+ return false;
}
- if (_sdkConfig.baseEndpoint.EndsWith('/'))
+ if (config.BaseEndpoint.EndsWith('/'))
{
Log.Error(() => "Please remove the '/' character at the end of the endpoint URL");
- return;
+ return false;
}
+ return true;
+ }
- // In the following code we compose our SDK
+ ///
+ /// Registers services and initializes all SDK components.
+ ///
+ public static async Task InitializeAsync(MeticaConfiguration config)
+ {
+ CheckConfig(config);
+ if (Sdk != null)
+ {
+ Log.Warning(() => "Metica SDK reinitialized. This means a new initialization was done on top of a previous one.");
+ }
+ Sdk = new MeticaSdk(config);
+
+ // ADS
+ var result = await MeticaAds.InitializeAsync(config);//InitializeAsync(config);
+ IsMeticaAdsEnabled = result.IsMeticaAdsEnabled;
+ return result;
+ }
+ ///
+ /// ORIGINAL SDK INITIALIZATION
+ ///
+ /// Metica SDK configuration object.
+ private MeticaSdk(MeticaConfiguration config)
+ {
_http = new HttpServiceDotnet(
- requestTimeoutSeconds: config.httpRequestTimeout,
+ requestTimeoutSeconds: 60,
cacheGCTimeoutSeconds: 10,
cacheTTLSeconds: 60
- ).WithPersistentHeaders(new Dictionary { { "X-API-Key", Config.apiKey } });
+ ).WithPersistentHeaders(new Dictionary { { "X-API-Key", config.ApiKey } });
// Initialize an OfferManager
- _offerManager = new OfferManager(_http, $"{Config.baseEndpoint}/offers/v1/apps/{Config.appId}");
+ _offerManager = new OfferManager(_http, $"{config.BaseEndpoint}/offers/v1/apps/{config.AppId}");
// Initialize a ConfigManager
- _configManager = new ConfigManager(_http, $"{Config.baseEndpoint}/configs/v1/apps/{Config.appId}");
+ _configManager = new ConfigManager(_http, $"{config.BaseEndpoint}/configs/v1/apps/{config.AppId}");
// Initialize an EventManager with _offerManager as IMeticaAttributesProvider
- _eventManager = new EventManager(_http, $"{Config.baseEndpoint}/ingest/v1/events", _offerManager, config.eventsLogDispatchMaxQueueSize);
- // Set the current (mutable) CurrentUserId with the initial value given in the configuration
- CurrentUserId = null;
- ApiKey = Config.apiKey;
- AppId = Config.appId;
- BaseEndpoint = Config.baseEndpoint;
-
- // Register this class as IMeticaSdk service in Registry
- Registry.Register(this);
- }
-
- public async Task GetOffersAsync(string[] placements, Dictionary userData = null)
- => await _offerManager.GetOffersAsync(CurrentUserId, placements, userData);
- [Obsolete]
- public async Task GetOffersAsync(string[] placements, Dictionary userData, DeviceInfo deviceInfo)
- => await _offerManager.GetOffersAsync(CurrentUserId, placements, userData);
-
-
- public async Task GetConfigsAsync(List configKeys = null, Dictionary userProperties = null)
- => await _configManager.GetConfigsAsync(CurrentUserId, configKeys, userProperties);
- [Obsolete]
- public async Task GetConfigsAsync(List configKeys, Dictionary userProperties, DeviceInfo deviceInfo)
- => await _configManager.GetConfigsAsync(CurrentUserId, configKeys, userProperties);
+ _eventManager = new EventManager(_http, $"{config.BaseEndpoint}/ingest/v1/events", _offerManager);
+ // Set the CurrentUserId with the initial value given in the configuration
+ // - - - - - - - - - - -
- public void LogLoginEvent(Dictionary customPayload = null)
- => _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- EventTypes.Login,
- null,
- customPayload);
-
+ UserId = config.UserId;
+ ApiKey = config.ApiKey;
+ AppId = config.AppId;
+ BaseEndpoint = config.BaseEndpoint;
+ }
- public void LogInstallEvent(Dictionary customPayload = null)
- => _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- EventTypes.Install,
- null,
- customPayload);
+ public static async ValueTask DisposeAsync()
+ => await Sdk.SdkDisposeAsync();
+ private async ValueTask SdkDisposeAsync()
+ {
+ if (_eventManager != null) await _eventManager.DisposeAsync();
+ if (_offerManager != null) await _offerManager.DisposeAsync();
+ if (_configManager != null) await _configManager.DisposeAsync();
+ _http?.Dispose();
+ Ads.Dispose(); // TODO
+ Sdk = null;
+ }
- public void LogOfferPurchaseEvent(string placementId, string offerId, string currencyCode, double totalAmount, Dictionary customPayload = null)
- => _ = _eventManager.QueueEventWithMeticaAttributesAsync(
- CurrentUserId,
- Config.appId,
- placementId,
- offerId,
- EventTypes.OfferPurchase,
- new() {
- { nameof(currencyCode), currencyCode },
- { nameof(totalAmount), totalAmount },
- },
- customPayload);
+ #endregion Methods
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public void LogOfferPurchaseEventWithProductId(string productId, string currencyCode, double totalAmount, Dictionary customPayload = null)
- => _eventManager.QueueEventWithProductId(
- CurrentUserId,
- Config.appId,
- productId,
- EventTypes.OfferPurchase,
- new() {
- { nameof(currencyCode), currencyCode },
- { nameof(totalAmount), totalAmount },
- },
- customPayload);
+ #region Offers
+ public static class Offers
+ {
+ public static async Task GetOffersAsync(string[] placements, Dictionary userData = null)
+ => await Sdk._offerManager.GetOffersAsync(UserId, placements, userData);
+ }
- public void LogOfferInteractionEvent(string placementId, string offerId, string interactionType, Dictionary customPayload = null)
- => _ = _eventManager.QueueEventWithMeticaAttributesAsync(
- CurrentUserId,
- Config.appId,
- placementId,
- offerId,
- EventTypes.OfferInteraction,
- new() { { nameof(interactionType), interactionType } },
- customPayload);
+ #endregion Offers
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public void LogOfferInteractionEventWithProductId(string productId, string interactionType, Dictionary customPayload = null)
- => _eventManager.QueueEventWithProductId(
- CurrentUserId,
- Config.appId,
- productId,
- EventTypes.OfferInteraction,
- new() { { nameof(interactionType), interactionType} },
- customPayload);
+ #region SmartConfig
+ public static class SmartConfig
+ {
+ public static async Task GetConfigsAsync(List configKeys = null, Dictionary userProperties = null)
+ => await Sdk._configManager.GetConfigsAsync(UserId, configKeys, userProperties);
+ }
- public void LogOfferImpressionEvent(string placementId, string offerId, Dictionary customPayload = null)
- => _ = _eventManager.QueueEventWithMeticaAttributesAsync(
- CurrentUserId,
- Config.appId,
- placementId,
- offerId,
- EventTypes.OfferImpression,
- null,
- customPayload);
+ #endregion SmartConfig
- public void LogOfferImpressionEventWithProductId(string productId, Dictionary customPayload = null)
- => _eventManager.QueueEventWithProductId(
- CurrentUserId,
- Config.appId,
- productId,
- EventTypes.OfferImpression,
- null,
- customPayload);
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ #region Events
- public void LogAdRevenueEvent(string placement, string type, string source, string currencyCode, double totalAmount, Dictionary customPayload = null)
- => _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- EventTypes.AdRevenue,
- new() {
+ public static class Events
+ {
+ public static void LogLoginEvent(Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ EventTypes.Login,
+ null,
+ customPayload);
+
+ public static void LogInstallEvent(Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ EventTypes.Install,
+ null,
+ customPayload);
+
+ public static void LogOfferPurchaseEvent(string placementId, string offerId, string currencyCode, double totalAmount, Dictionary customPayload = null)
+ => _ = Sdk._eventManager.QueueEventWithMeticaAttributesAsync(
+ UserId,
+ AppId,
+ placementId,
+ offerId,
+ EventTypes.OfferPurchase,
+ new() {
+ { nameof(currencyCode), currencyCode },
+ { nameof(totalAmount), totalAmount },
+ },
+ customPayload);
+
+ public static void LogOfferPurchaseEventWithProductId(string productId, string currencyCode, double totalAmount, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventWithProductId(
+ UserId,
+ AppId,
+ productId,
+ EventTypes.OfferPurchase,
+ new() {
+ { nameof(currencyCode), currencyCode },
+ { nameof(totalAmount), totalAmount },
+ },
+ customPayload);
+
+ public static void LogOfferInteractionEvent(string placementId, string offerId, string interactionType, Dictionary customPayload = null)
+ => _ = Sdk._eventManager.QueueEventWithMeticaAttributesAsync(
+ UserId,
+ AppId,
+ placementId,
+ offerId,
+ EventTypes.OfferInteraction,
+ new() { { nameof(interactionType), interactionType } },
+ customPayload);
+
+ public static void LogOfferInteractionEventWithProductId(string productId, string interactionType, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventWithProductId(
+ UserId,
+ AppId,
+ productId,
+ EventTypes.OfferInteraction,
+ new() { { nameof(interactionType), interactionType } },
+ customPayload);
+
+ public static void LogOfferImpressionEvent(string placementId, string offerId, Dictionary customPayload = null)
+ => _ = Sdk._eventManager.QueueEventWithMeticaAttributesAsync(
+ UserId,
+ AppId,
+ placementId,
+ offerId,
+ EventTypes.OfferImpression,
+ null,
+ customPayload);
+
+ public static void LogOfferImpressionEventWithProductId(string productId, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventWithProductId(
+ UserId,
+ AppId,
+ productId,
+ EventTypes.OfferImpression,
+ null,
+ customPayload);
+
+ public static void LogAdRevenueEvent(string placement, string type, string source, string currencyCode, double totalAmount, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ EventTypes.AdRevenue,
+ new() {
{ nameof (placement), placement },
{ nameof (type), type },
{ nameof (source), source },
{ nameof (currencyCode), currencyCode },
{ nameof (totalAmount), totalAmount },
- },
+ },
+ customPayload);
+
+ public static void LogFullStateUserUpdateEvent(Dictionary userStateAttributes, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ EventTypes.FullStateUpdate,
+ new() { { nameof(userStateAttributes), userStateAttributes }, },
+ customPayload);
+
+ public static void LogPartialStateUserUpdateEvent(Dictionary userStateAttributes, Dictionary customPayload = null)
+ => Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ EventTypes.PartialStateUpdate,
+ new() { { nameof(userStateAttributes), userStateAttributes } },
+ customPayload);
+
+ public static void LogCustomEvent(string customEventType, Dictionary customPayload = null)
+ {
+ if (EventTypes.IsEventType(customEventType))
+ {
+ Log.Error(() => $"{customEventType} cannot be used with {nameof(LogCustomEvent)}. Please use an event type that is not a core event. See documentation at https://docs.metica.com/integration#core-events.");
+ return;
+ }
+ Sdk._eventManager.QueueEventAsync(
+ UserId,
+ AppId,
+ customEventType,
+ null,
customPayload);
+ }
+ public static void RequestDispatchEvents()
+ {
+ _ = Sdk._eventManager.RequestDispatchEvents();
+ }
+ }
+ #endregion Events
- public void LogFullStateUserUpdateEvent(Dictionary userStateAttributes, Dictionary customPayload = null)
- => _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- EventTypes.FullStateUpdate,
- new() { { nameof (userStateAttributes), userStateAttributes }, },
- customPayload);
-
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- public void LogPartialStateUserUpdateEvent(Dictionary userStateAttributes, Dictionary customPayload = null)
- => _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- EventTypes.PartialStateUpdate,
- new() { { nameof(userStateAttributes), userStateAttributes } },
- customPayload);
+ #region Ads
- public void LogCustomEvent(string customEventType, Dictionary customPayload = null)
+ // ADS bridge
+ public static class Ads
{
- if (EventTypes.IsEventType(customEventType))
- {
- Log.Error(() => $"{customEventType} cannot be used with {nameof(LogCustomEvent)}. Please use an event type that is not a core event. See documentation at https://docs.metica.com/integration#core-events.");
- return;
- }
- _eventManager.QueueEventAsync(
- CurrentUserId,
- Config.appId,
- customEventType,
- null,
- customPayload);
- }
+ public static void CreateBanner(string bannerAdUnitId, MeticaBannerPosition position)
+ => MeticaAds.CreateBanner(bannerAdUnitId, position);
- public void RequestDispatchEvents()
- {
- _ = _eventManager.RequestDispatchEvents();
- }
+ public static void ShowBanner(string adUnitId)
+ => MeticaAds.ShowBanner(adUnitId);
- public async ValueTask DisposeAsync()
- {
- if (_eventManager != null) await _eventManager.DisposeAsync();
- if (_offerManager != null) await _offerManager.DisposeAsync();
- if (_configManager != null) await _configManager.DisposeAsync();
- _http?.Dispose();
+ public static void HideBanner(string adUnitId)
+ => MeticaAds.HideBanner(adUnitId);
+
+ public static void DestroyBanner(string adUnitId)
+ => MeticaAds.DestroyBanner(adUnitId);
+
+ public static void LoadInterstitial(string interstitialAdUnitId)
+ => MeticaAds.LoadInterstitial(interstitialAdUnitId);
+
+ public static void ShowInterstitial(string interstitialAdUnitId)
+ => MeticaAds.ShowInterstitial(interstitialAdUnitId);
+
+ public static bool IsInterstitialReady(string interstitialAdUnitId)
+ => MeticaAds.IsInterstitialReady(interstitialAdUnitId);
+
+ public static void LoadRewarded(string rewardedAdUnitId)
+ => MeticaAds.LoadRewarded(rewardedAdUnitId);
+
+ public static void ShowRewarded(string rewardedAdUnitId)
+ => MeticaAds.ShowRewarded(rewardedAdUnitId);
+
+ public static bool IsRewardedReady(string rewardedAdUnitId)
+ => MeticaAds.IsRewardedReady(rewardedAdUnitId);
+
+ internal static void Dispose()
+ // TODO
+ => Log.Info(() => "Metica.Sdk.Ads.Dispose called but not yet implemented.");
}
+
+ #endregion Ads
}
}
diff --git a/Runtime/SDK/OfferManager.cs b/Runtime/SDK/OfferManager.cs
index 6457f9f..90f9639 100644
--- a/Runtime/SDK/OfferManager.cs
+++ b/Runtime/SDK/OfferManager.cs
@@ -70,7 +70,7 @@ public async Task