Skip to content

Commit 47e5d3b

Browse files
authored
Merge pull request #101 from IABTechLab/dave/euid-ima
EUID Support for IMA Plugin
2 parents c786b25 + 4791959 commit 47e5d3b

File tree

8 files changed

+157
-6
lines changed

8 files changed

+157
-6
lines changed

securesignals-ima-dev-app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
android:networkSecurityConfig="@xml/network_security_config"
1515
tools:ignore="UnusedAttribute">
1616

17+
<!-- Metadata for toggling UID2 and EUID environments. If true, EUID is used. -->
18+
<meta-data android:name="uid2_environment_euid" android:value="false"/>
19+
1720
<activity
1821
android:name=".MainActivity"
1922
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"

securesignals-ima-dev-app/src/main/java/com/uid2/dev/IMADevApplication.kt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ package com.uid2.dev
22

33
import android.app.Application
44
import android.util.Log
5+
import com.uid2.EUIDManager
56
import com.uid2.UID2Manager
67
import com.uid2.UID2Manager.Environment.Production
8+
import com.uid2.dev.utils.getMetadata
9+
import com.uid2.dev.utils.isEnvironmentEUID
710

811
class IMADevApplication : Application() {
912

@@ -13,11 +16,18 @@ class IMADevApplication : Application() {
1316
// Initialise the UID2Manager class. We will use it's DefaultNetworkSession rather than providing our own
1417
// custom implementation. This can be done to allow wrapping something like OkHttp.
1518
try {
16-
UID2Manager.init(
17-
context = this,
18-
environment = Production,
19-
isLoggingEnabled = true,
20-
)
19+
if (baseContext.getMetadata().isEnvironmentEUID()) {
20+
EUIDManager.init(
21+
context = this,
22+
isLoggingEnabled = true,
23+
)
24+
} else {
25+
UID2Manager.init(
26+
context = this,
27+
environment = Production,
28+
isLoggingEnabled = true,
29+
)
30+
}
2131
} catch (ex: Exception) {
2232
Log.e("IMADevApplication", "Error initialising UID2Manager", ex)
2333
}

securesignals-ima-dev-app/src/main/java/com/uid2/dev/MainActivity.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.uid2.dev;
22

3+
import static com.uid2.dev.utils.BundleExKt.isEnvironmentEUID;
4+
import static com.uid2.dev.utils.ContextExKt.getMetadata;
5+
36
import android.content.Context;
47
import android.media.AudioManager;
58
import android.os.Bundle;
@@ -22,6 +25,7 @@
2225
import com.google.ads.interactivemedia.v3.api.ImaSdkFactory;
2326
import com.google.ads.interactivemedia.v3.api.ImaSdkSettings;
2427
import com.google.ads.interactivemedia.v3.api.player.VideoProgressUpdate;
28+
import com.uid2.EUIDManager;
2529
import com.uid2.UID2Manager;
2630
import com.uid2.data.UID2Identity;
2731

@@ -227,7 +231,11 @@ private void loadUID2Identity() {
227231
refreshExpires,
228232
fromJsonIdentity.getRefreshResponseKey());
229233

230-
UID2Manager.getInstance().setIdentity(identity);
234+
if (isEnvironmentEUID(getMetadata(getBaseContext()))) {
235+
EUIDManager.getInstance().setIdentity(identity);
236+
} else {
237+
UID2Manager.getInstance().setIdentity(identity);
238+
}
231239
} catch (Exception e) {
232240
Log.e(LOGTAG, "Error loading Identity: " + e);
233241
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.uid2.dev.utils
2+
3+
import android.os.Bundle
4+
5+
private const val UID2_ENVIRONMENT_EUID = "uid2_environment_euid"
6+
7+
fun Bundle.isEnvironmentEUID(): Boolean = getBoolean(UID2_ENVIRONMENT_EUID, false)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.uid2.dev.utils
2+
3+
import android.content.Context
4+
import android.content.pm.PackageManager
5+
import android.os.Bundle
6+
7+
fun Context.getMetadata(): Bundle = packageManager.getApplicationInfoCompat(
8+
packageName,
9+
PackageManager.GET_META_DATA,
10+
).metaData
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.uid2.dev.utils
2+
3+
import android.content.pm.ApplicationInfo
4+
import android.content.pm.PackageManager
5+
import android.os.Build
6+
7+
fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int = 0): ApplicationInfo =
8+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
9+
@Suppress("WrongConstant")
10+
getApplicationInfo(packageName, PackageManager.ApplicationInfoFlags.of(flags.toLong()))
11+
} else {
12+
@Suppress("DEPRECATION")
13+
getApplicationInfo(packageName, flags)
14+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.uid2.securesignals.ima
2+
3+
import android.content.Context
4+
import com.google.ads.interactivemedia.v3.api.VersionInfo
5+
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsAdapter
6+
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsCollectSignalsCallback
7+
import com.google.ads.interactivemedia.v3.api.signals.SecureSignalsInitializeCallback
8+
import com.uid2.EUIDManager
9+
import com.uid2.UID2
10+
11+
/**
12+
* A custom exception type that is used to report failures from the EUIDSecureSignalsAdapter when an error has occurred.
13+
*/
14+
public class EUIDSecureSignalsException(message: String? = null, cause: Throwable? = null) : Exception(message, cause)
15+
16+
/**
17+
* An implementation of Google's IMA SecureSignalsAdapter that integrates UID2 tokens, accessed via the UID2Manager.
18+
*/
19+
public class EUIDSecureSignalsAdapter : SecureSignalsAdapter {
20+
21+
/**
22+
* Gets the version of the UID2 SDK.
23+
*/
24+
public override fun getSDKVersion(): VersionInfo = UID2.getVersionInfo().let {
25+
VersionInfo(it.major, it.minor, it.patch)
26+
}
27+
28+
/**
29+
* Gets the version of the UID2 Secure Signals plugin.
30+
*/
31+
public override fun getVersion(): VersionInfo = PluginVersion.getVersionInfo().let {
32+
VersionInfo(it.major, it.minor, it.patch)
33+
}
34+
35+
/**
36+
* Initialises the UID2 SDK with the given Context.
37+
*/
38+
public override fun initialize(context: Context, callback: SecureSignalsInitializeCallback) {
39+
// It's possible that the EUIDManager is already initialised. If so, it's a no-op.
40+
if (!EUIDManager.isInitialized()) {
41+
EUIDManager.init(context)
42+
}
43+
44+
// After we've asked to initialize the manager, we should wait until it's complete before reporting success.
45+
// This will potentially allow any previously persisted identity to be fully restored before we allow any
46+
// signals to be collected.
47+
EUIDManager.getInstance().addOnInitializedListener(callback::onSuccess)
48+
}
49+
50+
/**
51+
* Collects the UID2 advertising token, if available.
52+
*/
53+
public override fun collectSignals(context: Context, callback: SecureSignalsCollectSignalsCallback) {
54+
EUIDManager.getInstance().let { manager ->
55+
val token = manager.getAdvertisingToken()
56+
if (token != null) {
57+
callback.onSuccess(token)
58+
} else {
59+
// We include the IdentityStatus in the "error" to have better visibility on why the Advertising Token
60+
// was not present. There are a number of valid reasons why we don't have a token, but we are still
61+
// required to report these as "failures".
62+
callback.onFailure(
63+
EUIDSecureSignalsException(
64+
"No Advertising Token available (Status: ${manager.currentIdentityStatus.value})",
65+
),
66+
)
67+
}
68+
}
69+
}
70+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.uid2.securesignals.ima
2+
3+
import com.uid2.UID2
4+
import org.junit.Assert.assertEquals
5+
import org.junit.Test
6+
7+
class EUIDSecureSignalsAdapterTest {
8+
@Test
9+
fun `test SDK version`() {
10+
val adapter = UID2SecureSignalsAdapter()
11+
val version = adapter.sdkVersion
12+
val expectedVersion = UID2.getVersionInfo()
13+
14+
assertEquals(expectedVersion.major, version.majorVersion)
15+
assertEquals(expectedVersion.minor, version.minorVersion)
16+
assertEquals(expectedVersion.patch, version.microVersion)
17+
}
18+
19+
@Test
20+
fun `test plugin version`() {
21+
val adapter = UID2SecureSignalsAdapter()
22+
val version = adapter.version
23+
val expectedVersion = PluginVersion.getVersionInfo()
24+
25+
assertEquals(expectedVersion.major, version.majorVersion)
26+
assertEquals(expectedVersion.minor, version.minorVersion)
27+
assertEquals(expectedVersion.patch, version.microVersion)
28+
}
29+
}

0 commit comments

Comments
 (0)