Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 Singular
Copyright (c) 2025 Singular

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<dependencies>
<androidPackages>
<androidPackage spec="com.singular.sdk:singular_kids_sdk:12.6.0">
<androidPackage spec="com.singular.sdk:singular_kids_sdk:12.9.0">
<repositories>
<repository>https://maven.singular.net</repository>
</repositories>
</androidPackage>
</androidPackages>
<iosPods>
<iosPod name="Singular-Kids-SDK" version="12.6.0" minTargetSdk="12.0" bitcodeEnabled="false" addToAllTargets="false">
<iosPod name="Singular-Kids-SDK" version="12.8.0" minTargetSdk="12.0" bitcodeEnabled="false" addToAllTargets="false">
</iosPod>
</iosPods>
</dependencies>
Binary file not shown.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file removed SingularSDK/Plugins/Android/SingularUnityBridge.jar
Binary file not shown.
28 changes: 23 additions & 5 deletions SingularSDK/Plugins/iOS/SingularUnityWrapper.mm
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@ bool StartSingularSession_(const char* configString){
withSecret:apiSecret
andHandler:singularLinkHandler
withTimeout:shortlinkResolveTimeout];

NSDictionary* globalProperties = [config objectForKey:@"globalProperties"];

SingularConfig* singularConfig = [[SingularConfig alloc] initWithApiKey:apiKey andSecret:apiSecret];
singularConfig.shortLinkResolveTimeOut = shortlinkResolveTimeout;
Expand All @@ -161,6 +159,7 @@ bool StartSingularSession_(const char* configString){
handleConversionValuesUpdated(conversionValue ? [conversionValue intValue] : -1, coarse ? [coarse intValue] : -1, lock);
};

NSDictionary* globalProperties = [config objectForKey:@"globalProperties"];
if ([globalProperties count] > 0){
for (NSDictionary* property in [globalProperties allValues]) {
NSString* propertyKey = [property objectForKey:@"Key"];
Expand All @@ -185,8 +184,7 @@ bool StartSingularSession_(const char* configString){
singularConfig.deviceAttributionCallback = ^(NSDictionary *deviceAttributionInfo) {
handleDeviceAttributionData(deviceAttributionInfo);
};



NSString *customSdid = [config objectForKey:@"customSdid"];
singularConfig.customSdid = customSdid;

Expand All @@ -198,6 +196,16 @@ bool StartSingularSession_(const char* configString){
sendSdkMessage("SingularDidSetSdid", result);
};

NSArray *pushLinkPaths = [config objectForKey:@"pushNotificationLinkPath"];
if (pushLinkPaths && pushLinkPaths.count > 0) {
singularConfig.pushNotificationLinkPath = pushLinkPaths;
}

NSArray *brandedDomains = [config objectForKey:@"brandedDomains"];
if (brandedDomains && brandedDomains.count > 0) {
singularConfig.brandedDomains = brandedDomains;
}

[Singular start:singularConfig];

return true;
Expand Down Expand Up @@ -331,6 +339,16 @@ void SetAllowAutoIAPComplete_(bool allowed){
[Singular setAllowAutoIAPComplete:b];
}

void HandlePushNotification_(const char* payloadJson) {
NSError *error;
NSDictionary *pushPayloadDictionary = [NSJSONSerialization JSONObjectWithData:[[NSString stringWithUTF8String:payloadJson]
dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
if (error) { return; }
if (pushPayloadDictionary.allKeys.count == 0) { return; }

[Singular handlePushNotification:pushPayloadDictionary];
}

void SetBatchesEvents_(bool setBatches){
BOOL b = setBatches ? YES : NO;
[Singular setBatchesEvents:b];
Expand Down Expand Up @@ -475,7 +493,7 @@ void LimitDataSharing_(bool limitDataSharingValue) {
bool GetLimitDataSharing_() {
return [Singular getLimitDataSharing];
}

/* Global Properties */

const char* GetGlobalProperties_() {
Expand Down
8 changes: 7 additions & 1 deletion SingularSDK/Runtime/SingularSDK.asmdef
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"versionDefines": [
{
"name": "com.unity.purchasing",
"expression": "",
"define": "SINGULAR_SDK_IAP_ENABLED"
}
],
"noEngineReferences": false
}
77 changes: 63 additions & 14 deletions SingularSDK/Runtime/SingularSDK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class SingularSDK : MonoBehaviour
{
#region SDK properties

// init:
#region init properties
public string SingularAPIKey = "<YourAPIKey>";
public string SingularAPISecret = "<YourAPISecret>";
public bool InitializeOnAwake = true;
Expand All @@ -30,7 +30,7 @@ public class SingularSDK : MonoBehaviour
public static bool Initialized { get; private set; } = false;

private const string UNITY_WRAPPER_NAME = "Unity";
private const string UNITY_VERSION = "5.3.0-KIDS";
private const string UNITY_VERSION = "5.4.0-KIDS";

// ios-only:
[Obsolete]
Expand All @@ -39,12 +39,12 @@ public class SingularSDK : MonoBehaviour
public bool SKANEnabled = true;
public bool manualSKANConversionManagement = false;
public int waitForTrackingAuthorizationWithTimeoutInterval = 0;
#endregion // iOS-only

// android-only:
#region Android-only
public static string fcmDeviceToken = null;
public string facebookAppId;
public bool collectOAID = false;
public bool limitedIdentifiersEnabled = false;

private static string imei;
#if UNITY_ANDROID
Expand All @@ -55,13 +55,14 @@ public class SingularSDK : MonoBehaviour

static bool status = false;
#endif
#endregion //Android-only

// cross-os:
#region Cross-platform
private Dictionary<string, SingularGlobalProperty> globalProperties = new Dictionary<string, SingularGlobalProperty>();
private static bool? limitDataSharing = null;
private static string customUserId;

// deep links:
#region Deeplinks
public long ddlTimeoutSec = 0; // default value (0) sets to default timeout (60s)
public long sessionTimeoutSec = 0; // default value (0) sets to default timeout (60s)
public long shortlinkResolveTimeout = 0; // default value (0) sets to default timeout (10s)
Expand All @@ -75,27 +76,42 @@ public class SingularSDK : MonoBehaviour
private Int32 resolvedSingularLinkTime;
static Int32 cachedDDLMessageTime;
static string cachedDDLMessage;
#endregion // Deeplinks

// session management:
#region Session management
public static bool endSessionOnGoingToBackground = false;
public static bool restartSessionOnReturningToForeground = false;
#endregion // Session management

// admon/batching:
#region Admom/batching
public static bool batchEvents = false;
private const string ADMON_REVENUE_EVENT_NAME = "__ADMON_USER_LEVEL_REVENUE__";
#endregion // Admon/batching

// SDID:
#region SDID
public static string CustomSdid;
#endregion // SDID

#region Push Notifications
public string[] pushNotificationsLinkPaths;
#endregion // Push Notifications

#region Branded Domains
public string[] brandedDomains;
#endregion // Branded Domains

// handlers and callbacks:
#region Handlers and Callbacks
public static SingularLinkHandler registeredSingularLinkHandler = null;
public static SingularDeferredDeepLinkHandler registeredDDLHandler = null;
public static SingularConversionValueUpdatedHandler registeredConversionValueUpdatedHandler = null;
public static SingularConversionValuesUpdatedHandler registeredConversionValuesUpdatedHandler = null;
public static SingularDeviceAttributionCallbackHandler registeredDeviceAttributionCallbackHandler = null;
public static SingularSdidAccessorHandler registeredSdidAccessorHandler = null;
#endregion // Handlers and Callbacks

#endregion
#endregion // Cross-platform

#endregion // SDK properties

// The Singular SDK is initialized here
void Awake()
Expand Down Expand Up @@ -178,6 +194,8 @@ private static SingularConfig BuildSingularConfig()
config.SetValue("globalProperties", instance.globalProperties);
config.SetValue("sessionTimeoutSec", instance.sessionTimeoutSec);
config.SetValue("customSdid", CustomSdid);
config.SetValue("pushNotificationLinkPath", Utilities.DelimitedStringsArrayToArrayOfArrayOfString(instance.pushNotificationsLinkPaths, '/'));
config.SetValue("brandedDomains", instance.brandedDomains);
#if UNITY_ANDROID
config.SetValue("facebookAppId", instance.facebookAppId);
config.SetValue("customUserId", customUserId);
Expand All @@ -187,13 +205,14 @@ private static SingularConfig BuildSingularConfig()
config.SetValue("enableDeferredDeepLinks", enableDeferredDeepLinks);
config.SetValue("enableLogging", instance.enableLogging);
config.SetValue("logLevel", instance.logLevel);
if (SingularSDK.fcmDeviceToken != null){
if (SingularSDK.fcmDeviceToken != null)
{
config.SetValue("fcmDeviceToken", SingularSDK.fcmDeviceToken);
}
config.SetValue("collectOAID", instance.collectOAID);
config.SetValue("limitedIdentifiersEnabled", instance.limitedIdentifiersEnabled);

if (limitDataSharing != null) {
if (limitDataSharing != null)
{
config.SetValue("limitDataSharing", limitDataSharing);
}

Expand Down Expand Up @@ -296,6 +315,9 @@ private enum NSType
[DllImport("__Internal")]
private static extern void SetAllowAutoIAPComplete_(bool allowed);

[DllImport("__Internal")]
private static extern void HandlePushNotification_(string payloadJson);

[DllImport("__Internal")]
private static extern void SetBatchesEvents_(bool allowed);

Expand Down Expand Up @@ -838,6 +860,33 @@ public static void SetAllowAutoIAPComplete(bool allowed)
#endif
}

#region Push Notifications
public static void HandlePushNotification(Dictionary<string, string> pushNotificationPayload)
{
if (Application.isEditor ||
!Initialized ||
!instance)
{
SingularUnityLogger.LogDebug("HandlePushNotification called before Singular SDK initialized. ignoring.");
return;
}

if (pushNotificationPayload == null)
{
SingularUnityLogger.LogDebug("HandlePushNotification called with null. ignoring.");
return;
}

string payloadAsJsonString = JsonConvert.SerializeObject(pushNotificationPayload);
#if UNITY_IOS
HandlePushNotification_(payloadAsJsonString);
#elif UNITY_ANDROID
SingularUnityLogger.LogDebug("SingularSDK HandlePushNotification is an iOS-only API which is not availalbe for Android. skipping.");
#endif
}

#endregion // Push Notifications

void OnApplicationPause(bool paused)
{
if (!Initialized || !instance)
Expand Down
22 changes: 22 additions & 0 deletions SingularSDK/Runtime/Utilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Singular
{
public class Utilities
{
public static string[][] DelimitedStringsArrayToArrayOfArrayOfString(string[] delimitedStringsArray, char delimiter)
{
if (delimitedStringsArray == null || delimitedStringsArray.Length == 0)
{
SingularUnityLogger.LogDebug("push notification paths strings array is null or empty. skipping.");
return null;
}

string[][] arrayOfArrayOfString = new string[delimitedStringsArray.Length][];
for (int i = 0; i < delimitedStringsArray.Length; i++)
{
arrayOfArrayOfString[i] = delimitedStringsArray[i].Split(delimiter);
}

return arrayOfArrayOfString;
}
}
}
3 changes: 3 additions & 0 deletions SingularSDK/Runtime/Utilities.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "singular-unity-kids-package",
"version": "5.3.0",
"version": "5.4.0",
"displayName": "Singular Kids",
"description": "Singular Unity Kids Package",
"type": "library",
Expand Down