diff --git a/securesignals-ima-dev-app/src/main/AndroidManifest.xml b/securesignals-ima-dev-app/src/main/AndroidManifest.xml
index 13d22da..4852817 100644
--- a/securesignals-ima-dev-app/src/main/AndroidManifest.xml
+++ b/securesignals-ima-dev-app/src/main/AndroidManifest.xml
@@ -14,6 +14,9 @@
android:networkSecurityConfig="@xml/network_security_config"
tools:ignore="UnusedAttribute">
+
+
+
= Build.VERSION_CODES.TIRAMISU) {
+ @Suppress("WrongConstant")
+ getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong()))
+ } else {
+ @Suppress("DEPRECATION")
+ getApplicationInfo(packageName, flags)
+ }
diff --git a/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt b/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt
new file mode 100644
index 0000000..46c1eff
--- /dev/null
+++ b/securesignals-ima/src/main/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapter.kt
@@ -0,0 +1,70 @@
+package com.uid2.securesignals.ima
+
+import android.content.Context
+import com.google.ads.interactivemedia.v3.api.VersionInfo
+import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsAdapter
+import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsCollectSignalsCallback
+import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsInitializeCallback
+import com.uid2.EUIDManager
+import com.uid2.UID2
+
+/**
+ * A custom exception type that is used to report failures from the EUIDSecureSignalsAdapter when an error has occurred.
+ */
+public class EUIDSecureSignalsException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
+
+/**
+ * An implementation of Google's IMA SecureSignalsAdapter that integrates UID2 tokens, accessed via the UID2Manager.
+ */
+public class EUIDSecureSignalsAdapter : SecureSignalsAdapter {
+
+ /**
+ * Gets the version of the UID2 SDK.
+ */
+ public override fun getSDKVersion(): VersionInfo = UID2.getVersionInfo().let {
+ VersionInfo(it.major, it.minor, it.patch)
+ }
+
+ /**
+ * Gets the version of the UID2 Secure Signals plugin.
+ */
+ public override fun getVersion(): VersionInfo = PluginVersion.getVersionInfo().let {
+ VersionInfo(it.major, it.minor, it.patch)
+ }
+
+ /**
+ * Initialises the UID2 SDK with the given Context.
+ */
+ public override fun initialize(context: Context, callback: SecureSignalsInitializeCallback) {
+ // It's possible that the EUIDManager is already initialised. If so, it's a no-op.
+ if (!EUIDManager.isInitialized()) {
+ EUIDManager.init(context)
+ }
+
+ // After we've asked to initialize the manager, we should wait until it's complete before reporting success.
+ // This will potentially allow any previously persisted identity to be fully restored before we allow any
+ // signals to be collected.
+ EUIDManager.getInstance().addOnInitializedListener(callback::onSuccess)
+ }
+
+ /**
+ * Collects the UID2 advertising token, if available.
+ */
+ public override fun collectSignals(context: Context, callback: SecureSignalsCollectSignalsCallback) {
+ EUIDManager.getInstance().let { manager ->
+ val token = manager.getAdvertisingToken()
+ if (token != null) {
+ callback.onSuccess(token)
+ } else {
+ // We include the IdentityStatus in the "error" to have better visibility on why the Advertising Token
+ // was not present. There are a number of valid reasons why we don't have a token, but we are still
+ // required to report these as "failures".
+ callback.onFailure(
+ EUIDSecureSignalsException(
+ "No Advertising Token available (Status: ${manager.currentIdentityStatus.value})",
+ ),
+ )
+ }
+ }
+ }
+}
diff --git a/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt b/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt
new file mode 100644
index 0000000..2f2125e
--- /dev/null
+++ b/securesignals-ima/src/test/java/com/uid2/securesignals/ima/EUIDSecureSignalsAdapterTest.kt
@@ -0,0 +1,29 @@
+package com.uid2.securesignals.ima
+
+import com.uid2.UID2
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class EUIDSecureSignalsAdapterTest {
+ @Test
+ fun `test SDK version`() {
+ val adapter = UID2SecureSignalsAdapter()
+ val version = adapter.sdkVersion
+ val expectedVersion = UID2.getVersionInfo()
+
+ assertEquals(expectedVersion.major, version.majorVersion)
+ assertEquals(expectedVersion.minor, version.minorVersion)
+ assertEquals(expectedVersion.patch, version.microVersion)
+ }
+
+ @Test
+ fun `test plugin version`() {
+ val adapter = UID2SecureSignalsAdapter()
+ val version = adapter.version
+ val expectedVersion = PluginVersion.getVersionInfo()
+
+ assertEquals(expectedVersion.major, version.majorVersion)
+ assertEquals(expectedVersion.minor, version.minorVersion)
+ assertEquals(expectedVersion.patch, version.microVersion)
+ }
+}