From fa6ec41f72a1f3078a75fce9ee9f43b88237a5de Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker Date: Wed, 18 Mar 2026 13:26:47 -0400 Subject: [PATCH 1/3] feat: Allow Client to Manually Call Appsflyer Start --- .../kotlin/com/mparticle/kits/AppsFlyerKit.kt | 87 ++++-- src/test/kotlin/com/appsflyer/AppsFlyerLib.kt | 28 ++ .../com/mparticle/kits/AppsflyerKitTests.kt | 290 +++++++++++++++--- 3 files changed, 323 insertions(+), 82 deletions(-) diff --git a/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt b/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt index f0b6d0c..f09c731 100644 --- a/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt +++ b/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt @@ -29,6 +29,7 @@ import com.mparticle.MParticle import com.mparticle.commerce.CommerceEvent import com.mparticle.commerce.Product import com.mparticle.consent.ConsentState +import com.mparticle.identity.MParticleUser import com.mparticle.internal.Logger import com.mparticle.internal.MPUtility import org.json.JSONArray @@ -47,7 +48,8 @@ class AppsFlyerKit : KitIntegration.CommerceListener, AppsFlyerConversionListener, KitIntegration.ActivityListener, - KitIntegration.UserAttributeListener { + KitIntegration.UserAttributeListener, + KitIntegration.IdentityListener { override fun getInstance(): AppsFlyerLib = AppsFlyerLib.getInstance() override fun getName() = NAME @@ -62,12 +64,12 @@ class AppsFlyerKit : MParticle.getInstance()?.environment == MParticle.Environment.Development, ) settings[DEV_KEY]?.let { AppsFlyerLib.getInstance().init(it, this, context) } - setting?.get(SHARING_FILTER_FOR_PARTNERS)?.let { - applySharingFilterForPartners(it) - } val userConsentState = currentUser?.consentState setConsent(userConsentState) - AppsFlyerLib.getInstance().start(context.applicationContext) + updateCustomerUserIdFromMpid(currentUser?.id) + if (!isManualStart()) { + AppsFlyerLib.getInstance().start(context.applicationContext) + } AppsFlyerLib.getInstance().setCollectAndroidID(MParticle.isAndroidIdEnabled()) val integrationAttributes = HashMap(1) integrationAttributes[APPSFLYERID_INTEGRATION_KEY] = @@ -307,7 +309,9 @@ class AppsFlyerKit : override fun removeUserIdentity(identityType: MParticle.IdentityType) { with(instance) { - if (MParticle.IdentityType.CustomerId == identityType) { + if (isUserIdentificationMpid()) { + updateCustomerUserIdFromMpid(currentUser?.id) + } else if (MParticle.IdentityType.CustomerId == identityType) { setCustomerUserId("") } else if (MParticle.IdentityType.Email == identityType) { setUserEmails(AppsFlyerProperties.EmailsCryptType.NONE, "") @@ -320,7 +324,9 @@ class AppsFlyerKit : identity: String, ) { with(instance) { - if (MParticle.IdentityType.CustomerId == identityType) { + if (isUserIdentificationMpid()) { + updateCustomerUserIdFromMpid(currentUser?.id) + } else if (MParticle.IdentityType.CustomerId == identityType) { setCustomerUserId(identity) } else if (MParticle.IdentityType.Email == identityType) { setUserEmails(AppsFlyerProperties.EmailsCryptType.NONE, identity) @@ -330,6 +336,38 @@ class AppsFlyerKit : override fun logout(): List = emptyList() + override fun onIdentifyCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest, + ) { + updateCustomerUserIdFromMpid(mParticleUser.id) + } + + override fun onLoginCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest, + ) { + updateCustomerUserIdFromMpid(mParticleUser.id) + } + + override fun onLogoutCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest, + ) { + updateCustomerUserIdFromMpid(mParticleUser.id) + } + + override fun onModifyCompleted( + mParticleUser: MParticleUser, + filteredIdentityApiRequest: FilteredIdentityApiRequest, + ) { + updateCustomerUserIdFromMpid(mParticleUser.id) + } + + override fun onUserIdentified(mParticleUser: MParticleUser) { + updateCustomerUserIdFromMpid(mParticleUser.id) + } + private fun parseToNestedMap(jsonString: String): Map { val topLevelMap = mutableMapOf() try { @@ -559,7 +597,9 @@ class AppsFlyerKit : activity: Activity, bundle: Bundle?, ): List { - instance.start(activity) + if (!isManualStart()) { + instance.start(activity) + } return emptyList() } @@ -578,30 +618,13 @@ class AppsFlyerKit : override fun onActivityDestroyed(activity: Activity): List = emptyList() - override fun onSettingsUpdated(settings: Map) { - settings[SHARING_FILTER_FOR_PARTNERS]?.let { applySharingFilterForPartners(it) } - } + private fun isManualStart(): Boolean = settings[MANUAL_START]?.lowercase() == "true" - private fun applySharingFilterForPartners(jsonValue: String) { - val partners = parseSharingFilterForPartners(jsonValue) - if (!partners.isNullOrEmpty()) { - instance.setSharingFilterForPartners(*partners.toTypedArray()) - } - } + private fun isUserIdentificationMpid(): Boolean = settings[USER_IDENTIFICATION_TYPE] == USER_IDENTIFICATION_MPID - private fun parseSharingFilterForPartners(json: String?): List? { - if (json.isNullOrEmpty()) return null - return try { - val jsonWithFormat = json.replace("\\", "") - val array = JSONArray(jsonWithFormat) - List(array.length()) { i -> array.getString(i) } - } catch (e: JSONException) { - Logger.warning( - "AppsFlyer kit: failed to parse sharingFilterForPartners, " + - "consent filter for partners will not be applied. Error: ${e.message}", - ) - null - } + private fun updateCustomerUserIdFromMpid(mpid: Long?) { + if (!isUserIdentificationMpid() || mpid == null) return + instance.setCustomerUserId(mpid.toString()) } companion object { @@ -630,7 +653,9 @@ class AppsFlyerKit : } } - private const val SHARING_FILTER_FOR_PARTNERS = "sharingFilterForPartners" + const val MANUAL_START = "manualStart" + const val USER_IDENTIFICATION_TYPE = "userIdentificationType" + const val USER_IDENTIFICATION_MPID = "MPID" private const val CONSENT_MAPPING = "consentMapping" @Suppress("ktlint:standard:property-naming") diff --git a/src/test/kotlin/com/appsflyer/AppsFlyerLib.kt b/src/test/kotlin/com/appsflyer/AppsFlyerLib.kt index 0ce8e82..c5443c2 100644 --- a/src/test/kotlin/com/appsflyer/AppsFlyerLib.kt +++ b/src/test/kotlin/com/appsflyer/AppsFlyerLib.kt @@ -5,12 +5,40 @@ import android.content.Context class AppsFlyerLib { private var consentData: AppsFlyerConsent? = null + var startCallCount = 0 + private set + + var customerUserId: String? = null + private set + fun setConsentData(consent: AppsFlyerConsent) { consentData = consent } fun getConsentData(): AppsFlyerConsent? = consentData + fun start(context: Context) { + startCallCount++ + } + + fun setCustomerUserId(id: String?) { + customerUserId = id + } + + fun init( + devKey: String, + conversionListener: Any?, + context: Context, + ) {} + + fun setCollectAndroidID(collect: Boolean) {} + + fun getAppsFlyerUID(context: Context): String = "test-appsflyer-uid" + + fun subscribeForDeepLink(listener: Any?) {} + + fun setDebugLog(debug: Boolean) {} + fun getConsentState(): MutableMap { val stateMap = mutableMapOf() consentData?.let { consent -> diff --git a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt index f83866d..6902afc 100644 --- a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt +++ b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt @@ -76,57 +76,6 @@ class AppsflyerKitTests { Assert.assertTrue(name.isNotEmpty()) } - @Test - @Throws(Exception::class) - fun testParseSharingFilterForPartners_returnsListForValidJson() { - val method = - AppsFlyerKit::class.java.getDeclaredMethod( - "parseSharingFilterForPartners", - String::class.java, - ) - method.isAccessible = true - val result = method.invoke(kit, """["partner_1", "partner_2"]""") - Assert.assertEquals(listOf("partner_1", "partner_2"), result) - } - - @Test - @Throws(Exception::class) - fun testParseSharingFilterForPartners_returnsNullForEmptyInput() { - val method = - AppsFlyerKit::class.java.getDeclaredMethod( - "parseSharingFilterForPartners", - String::class.java, - ) - method.isAccessible = true - Assert.assertNull(method.invoke(kit, "")) - Assert.assertNull(method.invoke(kit, null)) - } - - @Test - @Throws(Exception::class) - fun testParseSharingFilterForPartners_returnsNullForInvalidJson() { - val method = - AppsFlyerKit::class.java.getDeclaredMethod( - "parseSharingFilterForPartners", - String::class.java, - ) - method.isAccessible = true - Assert.assertNull(method.invoke(kit, "not a json array")) - } - - @Test - @Throws(Exception::class) - fun testParseSharingFilterForPartners_stripsBackslashes() { - val method = - AppsFlyerKit::class.java.getDeclaredMethod( - "parseSharingFilterForPartners", - String::class.java, - ) - method.isAccessible = true - val result = method.invoke(kit, """[\"test_1\", \"test_2\"]""") - Assert.assertEquals(listOf("test_1", "test_2"), result) - } - /** * Kit *should* throw an exception when they're initialized with the wrong settings. * @@ -776,6 +725,245 @@ class AppsflyerKitTests { Assert.assertEquals(emptyMap(), result) } + // region manualStart and userIdentificationType (MPID) tests + + @Test + @Throws(Exception::class) + fun testIsManualStart_returnsTrueWhenSettingIsTrue() { + setKitSettings(mapOf(AppsFlyerKit.MANUAL_START to "true")) + val method = AppsFlyerKit::class.java.getDeclaredMethod("isManualStart") + method.isAccessible = true + Assert.assertTrue(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testIsManualStart_returnsFalseWhenSettingIsFalse() { + setKitSettings(mapOf(AppsFlyerKit.MANUAL_START to "false")) + val method = AppsFlyerKit::class.java.getDeclaredMethod("isManualStart") + method.isAccessible = true + Assert.assertFalse(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testIsManualStart_returnsFalseWhenSettingIsAbsent() { + setKitSettings(emptyMap()) + val method = AppsFlyerKit::class.java.getDeclaredMethod("isManualStart") + method.isAccessible = true + Assert.assertFalse(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testIsUserIdentificationMpid_returnsTrueWhenSettingIsMPID() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val method = + AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") + method.isAccessible = true + Assert.assertTrue(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testIsUserIdentificationMpid_returnsFalseWhenSettingIsAbsent() { + setKitSettings(emptyMap()) + val method = + AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") + method.isAccessible = true + Assert.assertFalse(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testIsUserIdentificationMpid_returnsFalseWhenSettingIsOther() { + setKitSettings(mapOf(AppsFlyerKit.USER_IDENTIFICATION_TYPE to "CustomerId")) + val method = + AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") + method.isAccessible = true + Assert.assertFalse(method.invoke(kit) as Boolean) + } + + @Test + @Throws(Exception::class) + fun testOnActivityCreated_withManualStartTrue_doesNotCallStart() { + setKitSettings( + mapOf( + AppsFlyerKit.MANUAL_START to "true", + ), + ) + kit.onActivityCreated(mock(Activity::class.java), null) + Assert.assertEquals(0, appsflyer.startCallCount) + } + + @Test + @Throws(Exception::class) + fun testOnActivityCreated_withManualStartFalse_callsStart() { + setKitSettings( + mapOf( + AppsFlyerKit.MANUAL_START to "false", + ), + ) + kit.onActivityCreated(mock(Activity::class.java), null) + Assert.assertEquals(1, appsflyer.startCallCount) + } + + @Test + @Throws(Exception::class) + fun testSetUserIdentity_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + // When userIdentificationType is MPID, identity callbacks set customer ID from user's MPID + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 12345L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertEquals("12345", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testSetUserIdentity_withoutUserIdentificationMpid_setsCustomerUserIdToIdentity() { + setKitSettings(emptyMap()) + + kit.setUserIdentity(MParticle.IdentityType.CustomerId, "custom-client-id") + + Assert.assertEquals("custom-client-id", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnIdentifyCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertEquals("54321", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnLoginCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onLoginCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertEquals("54321", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnLogoutCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onLogoutCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertEquals("54321", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnModifyCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onModifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertEquals("54321", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnUserIdentified_withUserIdentificationMpid_setsCustomerUserIdToMpid() { + setKitSettings( + mapOf( + AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, + ), + ) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onUserIdentified(user) + + Assert.assertEquals("54321", appsflyer.customerUserId) + } + + @Test + @Throws(Exception::class) + fun testOnIdentifyCompleted_withoutUserIdentificationMpid_doesNotSetCustomerUserIdFromMpid() { + setKitSettings(emptyMap()) + val mpid = 54321L + Mockito.`when`(user.getId()).thenReturn(mpid) + + kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) + + Assert.assertNull(appsflyer.customerUserId) + } + + @Throws(Exception::class) + private fun setKitSettings(settings: Map) { + val configJson = JSONObject() + configJson.put("id", "-1") + configJson.put("as", settings.toMutableMap()) + kit.configuration = KitConfiguration.createKitConfiguration(configJson) + } + + @Throws(Exception::class) + private fun setKitCurrentUser(user: FilteredMParticleUser?) { + var clazz: Class<*>? = kit.javaClass + while (clazz != null) { + for (field in clazz.declaredFields) { + val canSet = + field.type.isAssignableFrom(FilteredMParticleUser::class.java) || + (field.name.lowercase().contains("user") && !field.type.isPrimitive) + if (canSet) { + try { + field.isAccessible = true + field.set(kit, user) + return + } catch (_: Exception) { + // try next field + } + } + } + clazz = clazz.superclass + } + // No suitable field found - skip setting (e.g. base class structure differs) + } + + // endregion + private var emptyCoreCallbacks: CoreCallbacks = object : CoreCallbacks { var activity = Activity() From 4b39b632846c831537c4de52477d4c1249711f95 Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker Date: Thu, 19 Mar 2026 14:16:27 -0400 Subject: [PATCH 2/3] Remove MPID logic --- .../kotlin/com/mparticle/kits/AppsFlyerKit.kt | 54 +----- .../com/mparticle/kits/AppsflyerKitTests.kt | 170 +----------------- 2 files changed, 5 insertions(+), 219 deletions(-) diff --git a/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt b/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt index f09c731..0226a0b 100644 --- a/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt +++ b/src/main/kotlin/com/mparticle/kits/AppsFlyerKit.kt @@ -29,7 +29,6 @@ import com.mparticle.MParticle import com.mparticle.commerce.CommerceEvent import com.mparticle.commerce.Product import com.mparticle.consent.ConsentState -import com.mparticle.identity.MParticleUser import com.mparticle.internal.Logger import com.mparticle.internal.MPUtility import org.json.JSONArray @@ -48,8 +47,7 @@ class AppsFlyerKit : KitIntegration.CommerceListener, AppsFlyerConversionListener, KitIntegration.ActivityListener, - KitIntegration.UserAttributeListener, - KitIntegration.IdentityListener { + KitIntegration.UserAttributeListener { override fun getInstance(): AppsFlyerLib = AppsFlyerLib.getInstance() override fun getName() = NAME @@ -66,7 +64,6 @@ class AppsFlyerKit : settings[DEV_KEY]?.let { AppsFlyerLib.getInstance().init(it, this, context) } val userConsentState = currentUser?.consentState setConsent(userConsentState) - updateCustomerUserIdFromMpid(currentUser?.id) if (!isManualStart()) { AppsFlyerLib.getInstance().start(context.applicationContext) } @@ -309,9 +306,7 @@ class AppsFlyerKit : override fun removeUserIdentity(identityType: MParticle.IdentityType) { with(instance) { - if (isUserIdentificationMpid()) { - updateCustomerUserIdFromMpid(currentUser?.id) - } else if (MParticle.IdentityType.CustomerId == identityType) { + if (MParticle.IdentityType.CustomerId == identityType) { setCustomerUserId("") } else if (MParticle.IdentityType.Email == identityType) { setUserEmails(AppsFlyerProperties.EmailsCryptType.NONE, "") @@ -324,9 +319,7 @@ class AppsFlyerKit : identity: String, ) { with(instance) { - if (isUserIdentificationMpid()) { - updateCustomerUserIdFromMpid(currentUser?.id) - } else if (MParticle.IdentityType.CustomerId == identityType) { + if (MParticle.IdentityType.CustomerId == identityType) { setCustomerUserId(identity) } else if (MParticle.IdentityType.Email == identityType) { setUserEmails(AppsFlyerProperties.EmailsCryptType.NONE, identity) @@ -336,38 +329,6 @@ class AppsFlyerKit : override fun logout(): List = emptyList() - override fun onIdentifyCompleted( - mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest, - ) { - updateCustomerUserIdFromMpid(mParticleUser.id) - } - - override fun onLoginCompleted( - mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest, - ) { - updateCustomerUserIdFromMpid(mParticleUser.id) - } - - override fun onLogoutCompleted( - mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest, - ) { - updateCustomerUserIdFromMpid(mParticleUser.id) - } - - override fun onModifyCompleted( - mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest, - ) { - updateCustomerUserIdFromMpid(mParticleUser.id) - } - - override fun onUserIdentified(mParticleUser: MParticleUser) { - updateCustomerUserIdFromMpid(mParticleUser.id) - } - private fun parseToNestedMap(jsonString: String): Map { val topLevelMap = mutableMapOf() try { @@ -620,13 +581,6 @@ class AppsFlyerKit : private fun isManualStart(): Boolean = settings[MANUAL_START]?.lowercase() == "true" - private fun isUserIdentificationMpid(): Boolean = settings[USER_IDENTIFICATION_TYPE] == USER_IDENTIFICATION_MPID - - private fun updateCustomerUserIdFromMpid(mpid: Long?) { - if (!isUserIdentificationMpid() || mpid == null) return - instance.setCustomerUserId(mpid.toString()) - } - companion object { const val DEV_KEY = "devKey" const val APPSFLYERID_INTEGRATION_KEY = "appsflyer_id_integration_setting" @@ -654,8 +608,6 @@ class AppsFlyerKit : } const val MANUAL_START = "manualStart" - const val USER_IDENTIFICATION_TYPE = "userIdentificationType" - const val USER_IDENTIFICATION_MPID = "MPID" private const val CONSENT_MAPPING = "consentMapping" @Suppress("ktlint:standard:property-naming") diff --git a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt index 6902afc..2212b42 100644 --- a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt +++ b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt @@ -725,7 +725,7 @@ class AppsflyerKitTests { Assert.assertEquals(emptyMap(), result) } - // region manualStart and userIdentificationType (MPID) tests + // region manualStart tests @Test @Throws(Exception::class) @@ -754,40 +754,6 @@ class AppsflyerKitTests { Assert.assertFalse(method.invoke(kit) as Boolean) } - @Test - @Throws(Exception::class) - fun testIsUserIdentificationMpid_returnsTrueWhenSettingIsMPID() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val method = - AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") - method.isAccessible = true - Assert.assertTrue(method.invoke(kit) as Boolean) - } - - @Test - @Throws(Exception::class) - fun testIsUserIdentificationMpid_returnsFalseWhenSettingIsAbsent() { - setKitSettings(emptyMap()) - val method = - AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") - method.isAccessible = true - Assert.assertFalse(method.invoke(kit) as Boolean) - } - - @Test - @Throws(Exception::class) - fun testIsUserIdentificationMpid_returnsFalseWhenSettingIsOther() { - setKitSettings(mapOf(AppsFlyerKit.USER_IDENTIFICATION_TYPE to "CustomerId")) - val method = - AppsFlyerKit::class.java.getDeclaredMethod("isUserIdentificationMpid") - method.isAccessible = true - Assert.assertFalse(method.invoke(kit) as Boolean) - } - @Test @Throws(Exception::class) fun testOnActivityCreated_withManualStartTrue_doesNotCallStart() { @@ -814,24 +780,7 @@ class AppsflyerKitTests { @Test @Throws(Exception::class) - fun testSetUserIdentity_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - // When userIdentificationType is MPID, identity callbacks set customer ID from user's MPID - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 12345L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertEquals("12345", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testSetUserIdentity_withoutUserIdentificationMpid_setsCustomerUserIdToIdentity() { + fun testSetUserIdentity_setsCustomerUserIdToIdentity() { setKitSettings(emptyMap()) kit.setUserIdentity(MParticle.IdentityType.CustomerId, "custom-client-id") @@ -839,98 +788,6 @@ class AppsflyerKitTests { Assert.assertEquals("custom-client-id", appsflyer.customerUserId) } - @Test - @Throws(Exception::class) - fun testOnIdentifyCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertEquals("54321", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testOnLoginCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onLoginCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertEquals("54321", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testOnLogoutCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onLogoutCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertEquals("54321", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testOnModifyCompleted_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onModifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertEquals("54321", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testOnUserIdentified_withUserIdentificationMpid_setsCustomerUserIdToMpid() { - setKitSettings( - mapOf( - AppsFlyerKit.USER_IDENTIFICATION_TYPE to AppsFlyerKit.USER_IDENTIFICATION_MPID, - ), - ) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onUserIdentified(user) - - Assert.assertEquals("54321", appsflyer.customerUserId) - } - - @Test - @Throws(Exception::class) - fun testOnIdentifyCompleted_withoutUserIdentificationMpid_doesNotSetCustomerUserIdFromMpid() { - setKitSettings(emptyMap()) - val mpid = 54321L - Mockito.`when`(user.getId()).thenReturn(mpid) - - kit.onIdentifyCompleted(user, mock(FilteredIdentityApiRequest::class.java)) - - Assert.assertNull(appsflyer.customerUserId) - } - @Throws(Exception::class) private fun setKitSettings(settings: Map) { val configJson = JSONObject() @@ -939,29 +796,6 @@ class AppsflyerKitTests { kit.configuration = KitConfiguration.createKitConfiguration(configJson) } - @Throws(Exception::class) - private fun setKitCurrentUser(user: FilteredMParticleUser?) { - var clazz: Class<*>? = kit.javaClass - while (clazz != null) { - for (field in clazz.declaredFields) { - val canSet = - field.type.isAssignableFrom(FilteredMParticleUser::class.java) || - (field.name.lowercase().contains("user") && !field.type.isPrimitive) - if (canSet) { - try { - field.isAccessible = true - field.set(kit, user) - return - } catch (_: Exception) { - // try next field - } - } - } - clazz = clazz.superclass - } - // No suitable field found - skip setting (e.g. base class structure differs) - } - // endregion private var emptyCoreCallbacks: CoreCallbacks = From 4f268c675e56c57cdbdbe8e33e9bff957d5a974e Mon Sep 17 00:00:00 2001 From: Brandon Stalnaker Date: Fri, 20 Mar 2026 09:47:19 -0400 Subject: [PATCH 3/3] test fix --- .../kotlin/com/mparticle/kits/AppsflyerKitTests.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt index 2212b42..c79c7a6 100644 --- a/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt +++ b/src/test/kotlin/com/mparticle/kits/AppsflyerKitTests.kt @@ -778,16 +778,6 @@ class AppsflyerKitTests { Assert.assertEquals(1, appsflyer.startCallCount) } - @Test - @Throws(Exception::class) - fun testSetUserIdentity_setsCustomerUserIdToIdentity() { - setKitSettings(emptyMap()) - - kit.setUserIdentity(MParticle.IdentityType.CustomerId, "custom-client-id") - - Assert.assertEquals("custom-client-id", appsflyer.customerUserId) - } - @Throws(Exception::class) private fun setKitSettings(settings: Map) { val configJson = JSONObject()