From d92886ddc11e0e16b2870f55dff412b14fd4e938 Mon Sep 17 00:00:00 2001 From: Mansi Pandya Date: Fri, 21 Nov 2025 17:41:31 -0500 Subject: [PATCH 1/2] feat: Update Android Gradle plugin to 8.0.2 --- build.gradle | 24 +++++++++++++++++++----- gradle/wrapper/gradle-wrapper.properties | 2 +- src/main/AndroidManifest.xml | 3 +-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 6a3a6d6..dc9b3f6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { - ext.kotlin_version = '1.8.10' - if (!project.hasProperty('version') || project.version == 'unspecified') { + ext.kotlin_version = '2.0.20' + if (!project.hasProperty('version') || project.version.equals('unspecified')) { project.version = '+' } @@ -9,8 +9,9 @@ buildscript { mavenLocal() mavenCentral() } + dependencies { - classpath 'com.android.tools.build:gradle:7.4.1' + classpath 'com.android.tools.build:gradle:8.1.4' classpath 'com.mparticle:android-kit-plugin:' + project.version classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } @@ -18,7 +19,7 @@ buildscript { plugins { id "org.sonarqube" version "3.5.0.2730" - id "org.jlleitschuh.gradle.ktlint" version "11.2.0" + id "org.jlleitschuh.gradle.ktlint" version "13.0.0" } sonarqube { @@ -30,13 +31,26 @@ sonarqube { } apply plugin: 'org.jlleitschuh.gradle.ktlint' -apply plugin: 'com.mparticle.kit' apply plugin: 'kotlin-android' +apply plugin: 'com.mparticle.kit' android { + namespace 'com.mparticle.kits.leanplum' defaultConfig { minSdkVersion 16 } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + kotlinOptions { + jvmTarget = '17' + } + testOptions { + unitTests.all { + jvmArgs += ['--add-opens', 'java.base/java.lang=ALL-UNNAMED'] + } + } } repositories { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661..e1bef7e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 40fdd9f..c4e6c98 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,2 +1 @@ - - + From 7c21489fe7cacd4c630e6b73f0ff4426fa0f59ec Mon Sep 17 00:00:00 2001 From: Mansi Pandya Date: Tue, 20 Jan 2026 11:08:31 -0500 Subject: [PATCH 2/2] Fix Lint Issue --- build.gradle | 3 + .../kotlin/com/mparticle/kits/LeanplumKit.kt | 209 +++++++++++------- src/test/kotlin/com/leanplum/Leanplum.kt | 7 +- .../com/leanplum/LeanplumDeviceIdMode.kt | 4 +- .../com/mparticle/kits/LeanplumKitTests.kt | 38 ++-- 5 files changed, 152 insertions(+), 109 deletions(-) diff --git a/build.gradle b/build.gradle index dc9b3f6..23e6b6e 100644 --- a/build.gradle +++ b/build.gradle @@ -36,6 +36,9 @@ apply plugin: 'com.mparticle.kit' android { namespace 'com.mparticle.kits.leanplum' + buildFeatures { + buildConfig = true + } defaultConfig { minSdkVersion 16 } diff --git a/src/main/kotlin/com/mparticle/kits/LeanplumKit.kt b/src/main/kotlin/com/mparticle/kits/LeanplumKit.kt index fb50ea8..b0c137b 100644 --- a/src/main/kotlin/com/mparticle/kits/LeanplumKit.kt +++ b/src/main/kotlin/com/mparticle/kits/LeanplumKit.kt @@ -4,7 +4,6 @@ import android.R.attr import android.app.Application import android.content.Context import android.content.Intent -import android.text.TextUtils import com.leanplum.Leanplum import com.leanplum.LeanplumActivityHelper import com.leanplum.LeanplumDeviceIdMode @@ -12,25 +11,34 @@ import com.mparticle.MPEvent import com.mparticle.MParticle import com.mparticle.MParticle.IdentityType import com.mparticle.TypedUserAttributeListener -import com.mparticle.UserAttributeListenerType 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.kits.KitIntegration.* +import com.mparticle.kits.FilteredIdentityApiRequest +import com.mparticle.kits.FilteredMParticleUser +import com.mparticle.kits.KitIntegration.CommerceListener +import com.mparticle.kits.KitIntegration.EventListener +import com.mparticle.kits.KitIntegration.IdentityListener +import com.mparticle.kits.KitIntegration.PushListener +import com.mparticle.kits.KitIntegration.UserAttributeListener +import com.mparticle.kits.ReportingMessage import java.math.BigDecimal -import java.util.* - - -class LeanplumKit : KitIntegration(), UserAttributeListener, - KitIntegration.EventListener, CommerceListener, IdentityListener, PushListener{ - +import java.util.HashMap +import java.util.LinkedList + +class LeanplumKit : + KitIntegration(), + UserAttributeListener, + KitIntegration.EventListener, + CommerceListener, + IdentityListener, + PushListener { public override fun onKitCreate( settings: Map, - context: Context + context: Context, ): List { - val deviceIdType = settings[DEVICE_ID_TYPE] val userId = generateLeanplumId() @@ -45,80 +53,85 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, Leanplum.setAppIdForProductionMode(settings[APP_ID_KEY], settings[CLIENT_KEY_KEY]) } - //Starting Leanplum with empty map to avoid db query, setting it after calling async fun + // Starting Leanplum with empty map to avoid db query, setting it after calling async fun Leanplum.start(context, userId) LeanplumActivityHelper.enableLifecycleCallbacks(context.applicationContext as Application) - MParticle.getInstance()?.Identity()?.currentUser?.getUserAttributes() + MParticle + .getInstance() + ?.Identity() + ?.currentUser + ?.getUserAttributes() return listOf( ReportingMessage( this, ReportingMessage.MessageType.APP_STATE_TRANSITION, System.currentTimeMillis(), - null - ) + null, + ), ) } - private fun generateLeanplumId(): String? { - return MParticle.getInstance()?.Identity()?.currentUser?.let { + private fun generateLeanplumId(): String? = + MParticle.getInstance()?.Identity()?.currentUser?.let { generateLeanplumUserId( it, settings, - userIdentities + userIdentities, )?.ifEmpty { null } } - } override fun onIdentifyCompleted( mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest + filteredIdentityApiRequest: FilteredIdentityApiRequest, ) { - //do nothing + // do nothing } override fun onLoginCompleted( mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest + filteredIdentityApiRequest: FilteredIdentityApiRequest, ) { - //do nothing + // do nothing } override fun onLogoutCompleted( mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest + filteredIdentityApiRequest: FilteredIdentityApiRequest, ) { - //do nothing + // do nothing } override fun onModifyCompleted( mParticleUser: MParticleUser, - filteredIdentityApiRequest: FilteredIdentityApiRequest + filteredIdentityApiRequest: FilteredIdentityApiRequest, ) { - //do nothing + // do nothing } override fun onUserIdentified(mParticleUser: MParticleUser) { val userIdentities = mParticleUser.userIdentities val userId = generateLeanplumUserId(mParticleUser, settings, userIdentities) - //first set userId to effectively switch users + // first set userId to effectively switch users if (!KitUtils.isEmpty(userId)) { Leanplum.setUserId(userId) } - //then set the attributes of the new user + // then set the attributes of the new user try { - mParticleUser.getUserAttributes(object : TypedUserAttributeListener { - override fun onUserAttributesReceived( - userAttributes: Map, - userAttributeLists: Map?>, - mpid: Long - ) { - val attributes: MutableMap = HashMap() - attributes.putAll(userAttributes) - attributes.putAll(userAttributeLists) - setLeanplumUserAttributes(userIdentities, attributes) - } - }) + mParticleUser.getUserAttributes( + object : TypedUserAttributeListener { + override fun onUserAttributesReceived( + userAttributes: Map, + userAttributeLists: Map?>, + mpid: Long, + ) { + val attributes: MutableMap = HashMap() + attributes.putAll(userAttributes) + attributes.putAll(userAttributeLists) + setLeanplumUserAttributes(userIdentities, attributes) + } + }, + ) } catch (e: Exception) { Logger.warning(e, "Unable to fetch User Attributes") } @@ -126,10 +139,11 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, private fun setLeanplumUserAttributes( userIdentities: Map, - userAttributes: MutableMap + userAttributes: MutableMap, ) { - if (!userAttributes.containsKey(LEANPLUM_EMAIL_USER_ATTRIBUTE) && configuration.shouldSetIdentity( - IdentityType.Email + if (!userAttributes.containsKey(LEANPLUM_EMAIL_USER_ATTRIBUTE) && + configuration.shouldSetIdentity( + IdentityType.Email, ) ) { if (userIdentities.containsKey(IdentityType.Email)) { @@ -143,7 +157,7 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, } private fun setAttributesAndCheckId(userAttributes: MutableMap) { - //If by the time onKitCreated was called, userAttributes were not available to create a LeanplumId, creating and setting one + // If by the time onKitCreated was called, userAttributes were not available to create a LeanplumId, creating and setting one if (Leanplum.getUserId().isNullOrEmpty()) { generateLeanplumId()?.let { id -> Leanplum.setUserAttributes(id, userAttributes) @@ -153,35 +167,38 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, } else { Leanplum.setUserAttributes(userAttributes) } - //per Leanplum - it's a good idea to make sure the SDK refreshes itself + // per Leanplum - it's a good idea to make sure the SDK refreshes itself Leanplum.forceContentUpdate() } fun generateLeanplumUserId( user: MParticleUser?, settings: Map, - userIdentities: Map + userIdentities: Map, ): String? { var userId: String? = null if (USER_ID_CUSTOMER_ID_VALUE.equals( settings[USER_ID_FIELD_KEY], - ignoreCase = true - ) && configuration.shouldSetIdentity( - IdentityType.CustomerId + ignoreCase = true, + ) && + configuration.shouldSetIdentity( + IdentityType.CustomerId, ) ) { userId = userIdentities[IdentityType.CustomerId] } else if (USER_ID_EMAIL_VALUE.equals( settings[USER_ID_FIELD_KEY], - ignoreCase = true - ) && configuration.shouldSetIdentity( - IdentityType.Email + ignoreCase = true, + ) && + configuration.shouldSetIdentity( + IdentityType.Email, ) ) { userId = userIdentities[IdentityType.Email] } else if (USER_ID_MPID_VALUE.equals( - settings[USER_ID_FIELD_KEY], ignoreCase = true + settings[USER_ID_FIELD_KEY], + ignoreCase = true, ) ) { if (user != null) { @@ -193,20 +210,28 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, override fun getName(): String = NAME - //Leanplum doesn't have the notion of opt-out. + // Leanplum doesn't have the notion of opt-out. override fun setOptOut(optedOut: Boolean): List = emptyList() - override fun onSetUserAttribute(key: String, value: Any, user: FilteredMParticleUser) { + override fun onSetUserAttribute( + key: String, + value: Any, + user: FilteredMParticleUser, + ) { val attributes = mutableMapOf() attributes[key] = value setAttributesAndCheckId(attributes) } - override fun onSetUserTag(s: String, filteredMParticleUser: FilteredMParticleUser) {} + override fun onSetUserTag( + s: String, + filteredMParticleUser: FilteredMParticleUser, + ) {} + override fun onSetUserAttributeList( key: String, list: List, - user: FilteredMParticleUser + user: FilteredMParticleUser, ) { val attributes = mutableMapOf() attributes[key] = list @@ -217,7 +242,7 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, key: String?, incrementedBy: Number?, newValue: String, - user: FilteredMParticleUser? + user: FilteredMParticleUser?, ) { val attributes = mutableMapOf() attributes[attr.key.toString()] = newValue @@ -226,27 +251,29 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, override fun supportsAttributeLists(): Boolean = true - override fun onConsentStateUpdated( consentState: ConsentState, consentState1: ConsentState, - filteredMParticleUser: FilteredMParticleUser + filteredMParticleUser: FilteredMParticleUser, ) { } override fun onSetAllUserAttributes( attributes: Map, attributeLists: Map>, - user: FilteredMParticleUser + user: FilteredMParticleUser, ) { val map = mutableMapOf() map.putAll(attributes) map.putAll(attributeLists) setAttributesAndCheckId(map) - //we set user attributes on start so there's no point in doing it here as well. + // we set user attributes on start so there's no point in doing it here as well. } - override fun onRemoveUserAttribute(key: String, user: FilteredMParticleUser) { + override fun onRemoveUserAttribute( + key: String, + user: FilteredMParticleUser, + ) { val attributes = mutableMapOf() attributes[key] = null setAttributesAndCheckId(attributes) @@ -254,13 +281,15 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, override fun leaveBreadcrumb(s: String): List = emptyList() - - override fun logError(s: String, map: Map): List = emptyList() + override fun logError( + s: String, + map: Map, + ): List = emptyList() override fun logException( e: Exception, map: Map, - s: String + s: String, ): List = emptyList() override fun logEvent(mpEvent: MPEvent): List { @@ -270,7 +299,7 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, override fun logScreen( screenName: String, - attributes: Map + attributes: Map, ): List { Leanplum.advanceTo(screenName, attributes) return listOf( @@ -278,8 +307,8 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, this, ReportingMessage.MessageType.SCREEN_VIEW, System.currentTimeMillis(), - attributes - ) + attributes, + ), ) } @@ -287,26 +316,31 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, valueIncreased: BigDecimal, total: BigDecimal, eventName: String, - attributes: Map + attributes: Map, ): List { Leanplum.track(eventName, valueIncreased.toDouble(), attributes) return listOf( ReportingMessage.fromEvent( this, - MPEvent.Builder(eventName, MParticle.EventType.Transaction) - .customAttributes(attributes).build() - ) + MPEvent + .Builder(eventName, MParticle.EventType.Transaction) + .customAttributes(attributes) + .build(), + ), ) } - private fun logTransaction(event: CommerceEvent, product: Product) { + private fun logTransaction( + event: CommerceEvent, + product: Product, + ) { val eventAttributes = HashMap() CommerceEventUtils.extractActionAttributes(event, eventAttributes) Leanplum.track( Leanplum.PURCHASE_EVENT_NAME, product.totalAmount, product.name, - eventAttributes + eventAttributes, ) } @@ -315,8 +349,9 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, if (!KitUtils.isEmpty(event.productAction) && event.productAction.equals( Product.PURCHASE, - ignoreCase = true - ) && !event.products.isNullOrEmpty() + ignoreCase = true, + ) && + !event.products.isNullOrEmpty() ) { val productList = event.products if (productList != null) { @@ -351,16 +386,20 @@ class LeanplumKit : KitIntegration(), UserAttributeListener, } } - override fun willHandlePushMessage(intent: Intent): Boolean { - return intent.extras?.containsKey("lp_version") ?: false - } + override fun willHandlePushMessage(intent: Intent): Boolean = intent.extras?.containsKey("lp_version") ?: false - override fun onPushMessageReceived(context: Context, intent: Intent) { - //Firebase only + override fun onPushMessageReceived( + context: Context, + intent: Intent, + ) { + // Firebase only } - override fun onPushRegistration(s: String, s1: String): Boolean { - //Firebase only + override fun onPushRegistration( + s: String, + s1: String, + ): Boolean { + // Firebase only return false } diff --git a/src/test/kotlin/com/leanplum/Leanplum.kt b/src/test/kotlin/com/leanplum/Leanplum.kt index 7d56573..8fe97d9 100644 --- a/src/test/kotlin/com/leanplum/Leanplum.kt +++ b/src/test/kotlin/com/leanplum/Leanplum.kt @@ -1,12 +1,10 @@ package com.leanplum object Leanplum { - var mMode: LeanplumDeviceIdMode? = null var mAppID: String? = null var mAccessKey: String? = null - @JvmStatic var deviceId: String? = null @@ -16,7 +14,10 @@ object Leanplum { } @JvmStatic - fun setAppIdForProductionMode(appId: String?, accessKey: String?) { + fun setAppIdForProductionMode( + appId: String?, + accessKey: String?, + ) { mAppID = appId mAccessKey = accessKey } diff --git a/src/test/kotlin/com/leanplum/LeanplumDeviceIdMode.kt b/src/test/kotlin/com/leanplum/LeanplumDeviceIdMode.kt index 9fd8c3b..2a47329 100644 --- a/src/test/kotlin/com/leanplum/LeanplumDeviceIdMode.kt +++ b/src/test/kotlin/com/leanplum/LeanplumDeviceIdMode.kt @@ -1,5 +1,7 @@ package com.leanplum enum class LeanplumDeviceIdMode { - MD5_MAC_ADDRESS, ANDROID_ID, ADVERTISING_ID + MD5_MAC_ADDRESS, + ANDROID_ID, + ADVERTISING_ID, } diff --git a/src/test/kotlin/com/mparticle/kits/LeanplumKitTests.kt b/src/test/kotlin/com/mparticle/kits/LeanplumKitTests.kt index 65d3984..251d7d8 100644 --- a/src/test/kotlin/com/mparticle/kits/LeanplumKitTests.kt +++ b/src/test/kotlin/com/mparticle/kits/LeanplumKitTests.kt @@ -1,6 +1,5 @@ package com.mparticle.kits -import android.content.Context import com.leanplum.Leanplum import com.leanplum.LeanplumDeviceIdMode import com.mparticle.MParticle @@ -20,7 +19,6 @@ class LeanplumKitTests { private val userIdentities = HashMap() private val mockConfiguration = Mockito.mock(KitConfiguration::class.java) - @Test @Throws(Exception::class) fun testGetName() { @@ -46,7 +44,6 @@ class LeanplumKitTests { @Test @Throws(Exception::class) fun testGenerateMpidUserId() { - settings[LeanplumKit.USER_ID_FIELD_KEY] = LeanplumKit.USER_ID_MPID_VALUE userIdentities[IdentityType.Email] = "foo email" userIdentities[IdentityType.CustomerId] = "foo customer id" @@ -63,20 +60,20 @@ class LeanplumKitTests { @Test @Throws(Exception::class) fun testGenerateEmailUserId() { - settings[LeanplumKit.USER_ID_FIELD_KEY] = LeanplumKit.USER_ID_EMAIL_VALUE userIdentities[IdentityType.Email] = "foo email" userIdentities[IdentityType.CustomerId] = "foo customer id" Mockito.`when`(user.id).thenReturn(5L) - Mockito.`when`( - mockConfiguration.shouldSetIdentity( - ArgumentMatchers.any( - IdentityType::class.java - ) - ) - ).thenReturn(true) + Mockito + .`when`( + mockConfiguration.shouldSetIdentity( + ArgumentMatchers.any( + IdentityType::class.java, + ), + ), + ).thenReturn(true) kit.configuration = mockConfiguration var id = kit.generateLeanplumUserId(user, settings, userIdentities) Assert.assertEquals("foo email", id) @@ -88,20 +85,20 @@ class LeanplumKitTests { @Test @Throws(Exception::class) fun testGenerateCustomerIdlUserId() { - settings[LeanplumKit.USER_ID_FIELD_KEY] = LeanplumKit.USER_ID_CUSTOMER_ID_VALUE userIdentities[IdentityType.Email] = "foo email" userIdentities[IdentityType.CustomerId] = "foo customer id" Mockito.`when`(user.id).thenReturn(5L) - Mockito.`when`( - mockConfiguration.shouldSetIdentity( - ArgumentMatchers.any( - IdentityType::class.java - ) - ) - ).thenReturn(true) + Mockito + .`when`( + mockConfiguration.shouldSetIdentity( + ArgumentMatchers.any( + IdentityType::class.java, + ), + ), + ).thenReturn(true) kit.configuration = mockConfiguration var id = kit.generateLeanplumUserId(user, settings, userIdentities) Assert.assertEquals("foo customer id", id) @@ -115,7 +112,8 @@ class LeanplumKitTests { val mparticle = MockMParticle() MParticle.setInstance(mparticle) val mockDas = "mockDasValue" - Mockito.`when`(MParticle.getInstance()?.Identity()?.deviceApplicationStamp) + Mockito + .`when`(MParticle.getInstance()?.Identity()?.deviceApplicationStamp) .thenReturn(mockDas) mparticle.setAndroidIdDisabled(false)