From 9e3e03be8c269f48fa8fe62f71bbd5b7b4f2d1e3 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 11:32:40 +0200 Subject: [PATCH 1/9] feat(api): add debug geography override to consent manager API ConsentManager.Instance.SetDebugSettings(ConsentDebugSettings) lets a publisher test the consent form of another region without a VPN. The DTO carries a ConsentDebugGeography (Eea, RegulatedUsState, Other -- Google's DebugGeography values) and an optional list of test device ids; null clears a previous value. The natives apply it only in a debuggable build on an emulator, simulator or registered device and log why otherwise. SDK-1001 Co-Authored-By: Claude Fable 5.1 --- Runtime/Api/ConsentDebugSettings.cs | 16 ++++++++++++++++ Runtime/Api/ConsentDebugSettings.cs.meta | 11 +++++++++++ Runtime/Api/Enums/ConsentDebugGeography.cs | 14 ++++++++++++++ Runtime/Api/Enums/ConsentDebugGeography.cs.meta | 11 +++++++++++ Runtime/Api/Interfaces/IConsentManager.cs | 1 + Runtime/Api/Internal/ConsentManagerClient.cs | 2 ++ 6 files changed, 55 insertions(+) create mode 100644 Runtime/Api/ConsentDebugSettings.cs create mode 100644 Runtime/Api/ConsentDebugSettings.cs.meta create mode 100644 Runtime/Api/Enums/ConsentDebugGeography.cs create mode 100644 Runtime/Api/Enums/ConsentDebugGeography.cs.meta diff --git a/Runtime/Api/ConsentDebugSettings.cs b/Runtime/Api/ConsentDebugSettings.cs new file mode 100644 index 0000000..03470b5 --- /dev/null +++ b/Runtime/Api/ConsentDebugSettings.cs @@ -0,0 +1,16 @@ +// ReSharper disable CheckNamespace + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace AppodealStack.Cmp +{ + [Serializable] + [SuppressMessage("ReSharper", "NotAccessedField.Global")] + public sealed class ConsentDebugSettings + { + public ConsentDebugGeography Geography; + public List TestDeviceIds; + } +} diff --git a/Runtime/Api/ConsentDebugSettings.cs.meta b/Runtime/Api/ConsentDebugSettings.cs.meta new file mode 100644 index 0000000..a68f128 --- /dev/null +++ b/Runtime/Api/ConsentDebugSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0463740e3b3848c7ae4cef8ae10890f5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Api/Enums/ConsentDebugGeography.cs b/Runtime/Api/Enums/ConsentDebugGeography.cs new file mode 100644 index 0000000..470e323 --- /dev/null +++ b/Runtime/Api/Enums/ConsentDebugGeography.cs @@ -0,0 +1,14 @@ +// ReSharper disable CheckNamespace + +using System.Diagnostics.CodeAnalysis; + +namespace AppodealStack.Cmp +{ + [SuppressMessage("ReSharper", "UnusedMember.Global")] + public enum ConsentDebugGeography + { + Eea, + RegulatedUsState, + Other, + } +} diff --git a/Runtime/Api/Enums/ConsentDebugGeography.cs.meta b/Runtime/Api/Enums/ConsentDebugGeography.cs.meta new file mode 100644 index 0000000..ff7a3aa --- /dev/null +++ b/Runtime/Api/Enums/ConsentDebugGeography.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a13b3c220cf44c4aa5e4176bdc8ed637 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/Api/Interfaces/IConsentManager.cs b/Runtime/Api/Interfaces/IConsentManager.cs index 7182a21..888557b 100644 --- a/Runtime/Api/Interfaces/IConsentManager.cs +++ b/Runtime/Api/Interfaces/IConsentManager.cs @@ -19,6 +19,7 @@ public interface IConsentManager void Load(); void LoadAndShowConsentFormIfRequired(); + void SetDebugSettings(ConsentDebugSettings debugSettings); void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters); void ShowPrivacyOptionsForm(); void Revoke(); diff --git a/Runtime/Api/Internal/ConsentManagerClient.cs b/Runtime/Api/Internal/ConsentManagerClient.cs index 51d86d9..d5d6f52 100644 --- a/Runtime/Api/Internal/ConsentManagerClient.cs +++ b/Runtime/Api/Internal/ConsentManagerClient.cs @@ -41,6 +41,8 @@ internal ConsentManagerClient() public void LoadAndShowConsentFormIfRequired() => _consentManagerImpl?.LoadAndShowConsentFormIfRequired(); + public void SetDebugSettings(ConsentDebugSettings debugSettings) => _consentManagerImpl?.SetDebugSettings(debugSettings); + public void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters) => _consentManagerImpl?.RequestConsentInfoUpdate(consentInfoParameters); public void ShowPrivacyOptionsForm() => _consentManagerImpl?.ShowPrivacyOptionsForm(); From d1cc76fb60196f29cea5b4aa4fe0aee8399fcee5 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 11:32:40 +0200 Subject: [PATCH 2/9] feat(android): implement debug settings support Build com.appodeal.consent.ConsentDebugSettings from the DTO and pass it to ConsentManager.setDebugSettings. A null DTO is forwarded as a null argument: Unity resolves the single overload through its java.lang.Object placeholder match (ReflectionHelper scores any reference parameter for it). SDK-1001 Co-Authored-By: Claude Fable 5.1 --- .../Platforms/Android/AndroidCmpJavaHelper.cs | 25 +++++++++++++++++++ .../Android/AndroidConsentManager.cs | 5 ++++ 2 files changed, 30 insertions(+) diff --git a/Runtime/Platforms/Android/AndroidCmpJavaHelper.cs b/Runtime/Platforms/Android/AndroidCmpJavaHelper.cs index cf985b3..928924c 100644 --- a/Runtime/Platforms/Android/AndroidCmpJavaHelper.cs +++ b/Runtime/Platforms/Android/AndroidCmpJavaHelper.cs @@ -109,6 +109,31 @@ public static AndroidJavaObject GetConsentInfoParametersJavaObject(ConsentInfoPa ); } + public static AndroidJavaObject GetConsentDebugSettingsJavaObject(ConsentDebugSettings debugSettings) + { + if (debugSettings == null) return null; + + var geography = new AndroidJavaClass("com.appodeal.consent.ConsentDebugGeography").GetStatic(GetJavaGeographyName(debugSettings.Geography)); + var testDeviceIds = new AndroidJavaObject("java.util.ArrayList"); + foreach (string testDeviceId in (debugSettings.TestDeviceIds ?? Enumerable.Empty()).Where(id => !String.IsNullOrEmpty(id))) + { + testDeviceIds.Call("add", testDeviceId); + } + + return new AndroidJavaObject("com.appodeal.consent.ConsentDebugSettings", geography, testDeviceIds); + } + + private static string GetJavaGeographyName(ConsentDebugGeography geography) + { + return geography switch + { + ConsentDebugGeography.Eea => "EEA", + ConsentDebugGeography.RegulatedUsState => "REGULATED_US_STATE", + ConsentDebugGeography.Other => "OTHER", + _ => throw new ArgumentOutOfRangeException(nameof(geography), geography, "value must be assignable to ConsentDebugGeography") + }; + } + private static object GetJavaObject(object value) { return value switch diff --git a/Runtime/Platforms/Android/AndroidConsentManager.cs b/Runtime/Platforms/Android/AndroidConsentManager.cs index 9afd92b..543ec8b 100644 --- a/Runtime/Platforms/Android/AndroidConsentManager.cs +++ b/Runtime/Platforms/Android/AndroidConsentManager.cs @@ -86,6 +86,11 @@ public void LoadAndShowConsentFormIfRequired() ); } + public void SetDebugSettings(ConsentDebugSettings debugSettings) + { + _consentManagerJavaClass?.CallStatic("setDebugSettings", AndroidCmpJavaHelper.GetConsentDebugSettingsJavaObject(debugSettings)); + } + public void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters) { var paramsJavaObject = AndroidCmpJavaHelper.GetConsentInfoParametersJavaObject(consentInfoParameters); From 8bd9667b0a8588049fc7b9f4d27e4f8b3f7fa0e2 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 11:32:40 +0200 Subject: [PATCH 3/9] feat(ios): implement debug settings support One entry point, CMPUnityPluginConsentManagerSetDebugSettings(geography, testDeviceIds): the geography index maps to APDConsentDebugGeography in the bridge and the ids travel comma-joined. Any index outside the enum, -1 for a null DTO included, clears APDConsentManager.shared.debugSettings, mirroring the -1 convention of the dismissed callbacks. SDK-1001 Co-Authored-By: Claude Fable 5.1 --- Runtime/Platforms/iOS/IosConsentManager.cs | 21 +++++++++++++++++++++ Runtime/Plugins/iOS/CmpConsentManager.m | 14 ++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Runtime/Platforms/iOS/IosConsentManager.cs b/Runtime/Platforms/iOS/IosConsentManager.cs index 76d8b9e..edad825 100644 --- a/Runtime/Platforms/iOS/IosConsentManager.cs +++ b/Runtime/Platforms/iOS/IosConsentManager.cs @@ -3,6 +3,7 @@ // ReSharper disable CheckNamespace using System; +using System.Linq; using System.Runtime.InteropServices; using System.Diagnostics.CodeAnalysis; using AOT; @@ -36,6 +37,23 @@ public void LoadAndShowConsentFormIfRequired() CmpConsentManagerLoadAndShowConsentFormIfRequired(ConsentFormDismissed); } + public void SetDebugSettings(ConsentDebugSettings debugSettings) + { + if (debugSettings == null) + { + CmpConsentManagerSetDebugSettings(-1, null); + return; + } + + if (!Enum.IsDefined(typeof(ConsentDebugGeography), debugSettings.Geography)) + { + throw new ArgumentOutOfRangeException(nameof(debugSettings.Geography), debugSettings.Geography, "value must be assignable to ConsentDebugGeography"); + } + + string testDeviceIds = debugSettings.TestDeviceIds == null ? "" : String.Join(",", debugSettings.TestDeviceIds.Where(id => !String.IsNullOrEmpty(id))); + CmpConsentManagerSetDebugSettings((int)debugSettings.Geography, testDeviceIds); + } + public void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters) { var paramsStruct = IosConsentInfoParameters.FromDtoClass(consentInfoParameters); @@ -79,6 +97,9 @@ ConsentFormLoadSucceededCallback onConsentFormLoadSucceeded [DllImport("__Internal", EntryPoint = "CMPUnityPluginConsentManagerShowPrivacyOptionsForm")] private static extern void CmpConsentManagerShowPrivacyOptionsForm(ConsentFormDismissedCallback onConsentFormDismissed); + [DllImport("__Internal", EntryPoint = "CMPUnityPluginConsentManagerSetDebugSettings")] + private static extern void CmpConsentManagerSetDebugSettings(int geography, string testDeviceIds); + [DllImport("__Internal", EntryPoint = "CMPUnityPluginConsentManagerRequestConsentInfoUpdate")] private static extern void CmpConsentManagerRequestConsentInfoUpdate( IntPtr consentInfoParametersPtr, diff --git a/Runtime/Plugins/iOS/CmpConsentManager.m b/Runtime/Plugins/iOS/CmpConsentManager.m index 53886d2..7543ede 100644 --- a/Runtime/Plugins/iOS/CmpConsentManager.m +++ b/Runtime/Plugins/iOS/CmpConsentManager.m @@ -46,6 +46,20 @@ void CMPUnityPluginConsentManagerLoadAndShowConsentFormIfRequired(ConsentFormDis }]; } +void CMPUnityPluginConsentManagerSetDebugSettings(int geography, const char* testDeviceIds) { + APDConsentDebugGeography debugGeography; + switch (geography) { + case 0: debugGeography = APDConsentDebugGeographyEEA; break; + case 1: debugGeography = APDConsentDebugGeographyRegulatedUSState; break; + case 2: debugGeography = APDConsentDebugGeographyOther; break; + default: APDConsentManager.shared.debugSettings = nil; return; + } + + NSString* joinedTestDeviceIds = testDeviceIds ? [NSString stringWithUTF8String:testDeviceIds] : @""; + NSArray* ids = joinedTestDeviceIds.length > 0 ? [joinedTestDeviceIds componentsSeparatedByString:@","] : @[]; + APDConsentManager.shared.debugSettings = [[APDConsentDebugSettings alloc] initWithGeography:debugGeography testDeviceIds:ids]; +} + void CMPUnityPluginConsentManagerRequestConsentInfoUpdate(CMPUnityPluginConsentInfoParameters consentInfoParameters, ConsentInfoUpdateFailedCallback updateFailedCallback, ConsentInfoUpdateSucceededCallback updateSucceededCallback) { From 1da8b5b1fffb8115d50791eda0454e138809e2ae Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 11:32:40 +0200 Subject: [PATCH 4/9] feat(editor): implement debug settings support The Editor simulates the form itself, so the call only logs that it is ignored off-device. SDK-1001 Co-Authored-By: Claude Fable 5.1 --- Runtime/Platforms/Editor/EditorConsentManager.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Runtime/Platforms/Editor/EditorConsentManager.cs b/Runtime/Platforms/Editor/EditorConsentManager.cs index 62f858e..a94bd05 100644 --- a/Runtime/Platforms/Editor/EditorConsentManager.cs +++ b/Runtime/Platforms/Editor/EditorConsentManager.cs @@ -80,6 +80,11 @@ public void LoadAndShowConsentFormIfRequired() editorConsentForm.Show(); } + public void SetDebugSettings(ConsentDebugSettings debugSettings) + { + Debug.Log("[Appodeal CMP] Debug settings are applied on Android and iOS only, the Editor ignores them"); + } + public void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters) { _isConsentInfoRequested = true; From 15f11d038cd6e8a2d9fd200c3be7f5b7ebcecb5f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 11:32:40 +0200 Subject: [PATCH 5/9] feat(dummy): implement debug settings support SDK-1001 Co-Authored-By: Claude Fable 5.1 --- Runtime/Platforms/Dummy/DummyConsentManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Runtime/Platforms/Dummy/DummyConsentManager.cs b/Runtime/Platforms/Dummy/DummyConsentManager.cs index 9e23763..1ca2307 100644 --- a/Runtime/Platforms/Dummy/DummyConsentManager.cs +++ b/Runtime/Platforms/Dummy/DummyConsentManager.cs @@ -25,6 +25,8 @@ public event EventHandler OnConsentFormDismissed public void LoadAndShowConsentFormIfRequired() => DisplayUnsupportedPlatformWarning(); + public void SetDebugSettings(ConsentDebugSettings debugSettings) => DisplayUnsupportedPlatformWarning(); + public void RequestConsentInfoUpdate(ConsentInfoParameters consentInfoParameters) => DisplayUnsupportedPlatformWarning(); public void ShowPrivacyOptionsForm() => DisplayUnsupportedPlatformWarning(); From 52a1b115e9803da95e664b35e97df54796f91e7d Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 14:27:54 +0200 Subject: [PATCH 6/9] feat(sample): set debug geography before requesting consent info in demo The natives read the override at request time, so the demo shows the required order: SetDebugSettings, then RequestConsentInfoUpdate. SDK-1001 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_016jfw3fMgkKyrhuubSbQxXB --- Samples~/UsageSample/AppodealCmpDemo.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Samples~/UsageSample/AppodealCmpDemo.cs b/Samples~/UsageSample/AppodealCmpDemo.cs index fea6f5a..b121999 100644 --- a/Samples~/UsageSample/AppodealCmpDemo.cs +++ b/Samples~/UsageSample/AppodealCmpDemo.cs @@ -94,6 +94,10 @@ public void RequestConsentInfoUpdate() Debug.Log($"[Appodeal CMP] init params: {parameters.ToJsonString()}"); + var debugSettings = new ConsentDebugSettings { Geography = ConsentDebugGeography.Eea }; + Debug.Log($"[Appodeal CMP] SetDebugSettings() method called, geography: {debugSettings.Geography}"); + ConsentManager.Instance.SetDebugSettings(debugSettings); + ConsentManager.Instance.RequestConsentInfoUpdate(parameters); } From 3620c37b20b281ca81159482e9ac325bc2bbd296 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 14:27:54 +0200 Subject: [PATCH 7/9] docs(changelog): add 2.2.0 entry SDK-1001 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_016jfw3fMgkKyrhuubSbQxXB --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47ac71f..8a23377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Changelog +### v2.2.0 (TBD) + ++ Added debug geography override support: `SetDebugSettings()` method, `ConsentDebugSettings` class and `ConsentDebugGeography` enum. Call it before `RequestConsentInfoUpdate()`; the natives honour it only in a debuggable build on an emulator, simulator or listed test device + ### v2.1.0 (June 23, 2026) + Added Privacy Options Form support: `ShowPrivacyOptionsForm()` method and `PrivacyOptionsStatus` property From 8fda4604caf8850de88f7e1d9fc3160111355e9f Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 14:27:54 +0200 Subject: [PATCH 8/9] chore(release): bump plugin version to 2.2.0 SDK-1001 Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_016jfw3fMgkKyrhuubSbQxXB --- Runtime/Api/ConsentManager.cs | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Runtime/Api/ConsentManager.cs b/Runtime/Api/ConsentManager.cs index 6503c29..1974233 100644 --- a/Runtime/Api/ConsentManager.cs +++ b/Runtime/Api/ConsentManager.cs @@ -9,7 +9,7 @@ namespace AppodealStack.Cmp [SuppressMessage("ReSharper", "UnusedMember.Global")] public static class ConsentManager { - private const string Version = "2.1.0"; + private const string Version = "2.2.0"; private static readonly Lazy Lazy = new Lazy(() => new ConsentManagerClient()); public static IConsentManager Instance { get => Lazy.Value; } diff --git a/package.json b/package.json index 5d4622b..cacb933 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "com.appodeal.cmp", - "version": "2.1.0", + "version": "2.2.0", "displayName": "Appodeal CMP", "description": "A Consent Management Platform (CMP) is a software that develops notices to inform users and capture their preferences with respect to the processing of their personal data.", "unity": "2021.3", From 0860709c2d85d5982acf0f51f16746fc77117f3c Mon Sep 17 00:00:00 2001 From: Vladimir Date: Wed, 9 Sep 2026 16:57:32 +0200 Subject: [PATCH 9/9] chore(deps): bump com.appodeal.mediation to 4.4.0 for new CMP SDK API 4.4.0 is the first mediation release whose Android core (4.4.0, Jira version 41706) and iOS pod (StackConsentManager 4.2.0) both carry ConsentManager debug settings. SDK-1001 Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 3 ++- package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a23377..616d309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ ### v2.2.0 (TBD) -+ Added debug geography override support: `SetDebugSettings()` method, `ConsentDebugSettings` class and `ConsentDebugGeography` enum. Call it before `RequestConsentInfoUpdate()`; the natives honour it only in a debuggable build on an emulator, simulator or listed test device ++ Added debug geography override support: `SetDebugSettings()` method, `ConsentDebugSettings` class and `ConsentDebugGeography` enum ++ Bumped `com.appodeal.mediation` dependency to v4.4.0 ### v2.1.0 (June 23, 2026) diff --git a/package.json b/package.json index cacb933..71d7c7a 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "unity": "2021.3", "documentationUrl": "https://docs.appodeal.com/unity/data-protection/gdpr-and-ccpa", "dependencies": { - "com.appodeal.mediation": "4.2.0" + "com.appodeal.mediation": "4.4.0" }, "keywords": [ "CMP",