diff --git a/build.gradle b/build.gradle
index a23f92d..4264768 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.8.10'
+ ext.kotlin_version = '2.0.20'
if (!project.hasProperty('version') || project.version.equals('unspecified')) {
project.version = '+'
}
@@ -11,7 +11,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.4.2'
+ 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"
}
@@ -19,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 {
@@ -31,14 +31,29 @@ 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.apptentive'
+ buildFeatures {
+ buildConfig = true
+ }
defaultConfig {
minSdkVersion 21
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
+ testOptions {
+ unitTests.all {
+ jvmArgs += ['--add-opens', 'java.base/java.lang=ALL-UNNAMED']
+ }
+ }
}
allprojects {
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 227314e..6136329 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/main/kotlin/com/mparticle/kits/ApptentiveKit.kt b/src/main/kotlin/com/mparticle/kits/ApptentiveKit.kt
index 0e29039..e367628 100644
--- a/src/main/kotlin/com/mparticle/kits/ApptentiveKit.kt
+++ b/src/main/kotlin/com/mparticle/kits/ApptentiveKit.kt
@@ -15,12 +15,15 @@ import com.mparticle.identity.MParticleUser
import com.mparticle.internal.Logger
import com.mparticle.kits.KitIntegration.IdentityListener
import com.mparticle.kits.KitIntegration.UserAttributeListener
-import java.util.*
+import java.util.LinkedList
import java.util.concurrent.TimeUnit
import kotlin.collections.HashMap
@OptIn(InternalUseOnly::class)
-class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityListener,
+class ApptentiveKit :
+ KitIntegration(),
+ KitIntegration.EventListener,
+ IdentityListener,
UserAttributeListener {
private var enableTypeDetection = true
private var lastKnownFirstName: String? = null
@@ -31,7 +34,7 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
override fun onKitCreate(
settings: Map,
- context: Context
+ context: Context,
): List {
val apptentiveAppKey = settings[APPTENTIVE_APP_KEY]
val apptentiveAppSignature = settings[APPTENTIVE_APP_SIGNATURE]
@@ -51,14 +54,15 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
configuration.shouldInheritAppTheme =
StringUtils.tryParseSettingFlag(settings, SHOULD_INHERIT_APP_THEME, true)
configuration.customAppStoreURL = settings[CUSTOM_APP_STORE_URL]
- configuration.ratingInteractionThrottleLength = StringUtils.tryParseLongSettingFlag(
- settings,
- RATING_INTERACTION_THROTTLE_LENGTH,
- TimeUnit.DAYS.toMillis(7)
- )
+ configuration.ratingInteractionThrottleLength =
+ StringUtils.tryParseLongSettingFlag(
+ settings,
+ RATING_INTERACTION_THROTTLE_LENGTH,
+ TimeUnit.DAYS.toMillis(7),
+ )
Apptentive.register(
context.applicationContext as Application,
- configuration
+ configuration,
) { registerResult ->
if (registerResult is RegisterResult.Success) {
Apptentive.setMParticleId(currentUser?.id.toString())
@@ -75,9 +79,9 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
override fun onConsentStateUpdated(
oldState: ConsentState?,
newState: ConsentState?,
- user: FilteredMParticleUser?
+ user: FilteredMParticleUser?,
) {
- //Ignored
+ // Ignored
}
//endregion
@@ -87,18 +91,25 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
key: String?,
incrementedBy: Number?,
value: String?,
- user: FilteredMParticleUser?
+ user: FilteredMParticleUser?,
) {
- //Ignored
+ // Ignored
}
- override fun onRemoveUserAttribute(key: String?, user: FilteredMParticleUser?) {
+ override fun onRemoveUserAttribute(
+ key: String?,
+ user: FilteredMParticleUser?,
+ ) {
key?.let {
Apptentive.removeCustomPersonData(it)
}
}
- override fun onSetUserAttribute(key: String?, value: Any?, user: FilteredMParticleUser?) {
+ override fun onSetUserAttribute(
+ key: String?,
+ value: Any?,
+ user: FilteredMParticleUser?,
+ ) {
if (key != null && value != null) {
when (key.lowercase()) {
MParticle.UserAttributes.FIRSTNAME.lowercase() -> {
@@ -113,7 +124,8 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
}
}
val fullName =
- listOfNotNull(lastKnownFirstName, lastKnownLastName).joinToString(separator = " ")
+ listOfNotNull(lastKnownFirstName, lastKnownLastName)
+ .joinToString(separator = " ")
.trim()
if (fullName.isNotBlank()) {
Logger.debug("Setting user name $fullName")
@@ -122,36 +134,43 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
}
}
- override fun onSetUserTag(key: String?, user: FilteredMParticleUser?) {
- //Ignored
+ override fun onSetUserTag(
+ key: String?,
+ user: FilteredMParticleUser?,
+ ) {
+ // Ignored
}
override fun onSetUserAttributeList(
attributeKey: String?,
attributeValueList: MutableList?,
- user: FilteredMParticleUser?
+ user: FilteredMParticleUser?,
) {
- //Ignored
+ // Ignored
}
override fun onSetAllUserAttributes(
userAttributes: MutableMap?,
userAttributeLists: MutableMap>?,
- user: FilteredMParticleUser?
+ user: FilteredMParticleUser?,
) {
userAttributes?.let { userAttribute ->
val firstName = userAttribute[MParticle.UserAttributes.FIRSTNAME] ?: ""
val lastName = userAttribute[MParticle.UserAttributes.LASTNAME] ?: ""
- val fullName = listOfNotNull(firstName, lastName).joinToString(separator = " ").trim()
+ val fullName =
+ listOfNotNull(firstName, lastName)
+ .joinToString(separator = " ")
+ .trim()
if (fullName.isNotBlank()) {
Logger.debug("Setting user name $fullName")
Apptentive.setPersonName(fullName)
}
- userAttribute.filterKeys { key ->
- key != MParticle.UserAttributes.FIRSTNAME && key != MParticle.UserAttributes.LASTNAME
- }.map {
- addCustomPersonData(it.key, it.value)
- }
+ userAttribute
+ .filterKeys { key ->
+ key != MParticle.UserAttributes.FIRSTNAME && key != MParticle.UserAttributes.LASTNAME
+ }.map {
+ addCustomPersonData(it.key, it.value)
+ }
}
}
@@ -162,14 +181,13 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
override fun logError(
message: String,
- errorAttributes: Map
+ errorAttributes: Map,
): List = emptyList()
-
override fun logException(
exception: Exception,
exceptionAttributes: Map,
- message: String
+ message: String,
): List = emptyList()
override fun logEvent(event: MPEvent): List {
@@ -181,7 +199,7 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
override fun logScreen(
screenName: String,
- eventAttributes: Map
+ eventAttributes: Map,
): List {
engage(screenName, eventAttributes)
val messages = LinkedList()
@@ -190,8 +208,8 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
this,
ReportingMessage.MessageType.SCREEN_VIEW,
System.currentTimeMillis(),
- eventAttributes
- )
+ eventAttributes,
+ ),
)
return messages
} //endregion
@@ -199,41 +217,41 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
//region IdentityListener
override fun onIdentifyCompleted(
mParticleUser: MParticleUser?,
- identityApiRequest: FilteredIdentityApiRequest?
+ identityApiRequest: FilteredIdentityApiRequest?,
) {
setUserIdentity(mParticleUser)
}
override fun onLoginCompleted(
mParticleUser: MParticleUser?,
- identityApiRequest: FilteredIdentityApiRequest?
+ identityApiRequest: FilteredIdentityApiRequest?,
) {
setUserIdentity(mParticleUser)
}
override fun onLogoutCompleted(
mParticleUser: MParticleUser?,
- identityApiRequest: FilteredIdentityApiRequest?
+ identityApiRequest: FilteredIdentityApiRequest?,
) {
setUserIdentity(mParticleUser)
}
override fun onModifyCompleted(
mParticleUser: MParticleUser?,
- identityApiRequest: FilteredIdentityApiRequest?
+ identityApiRequest: FilteredIdentityApiRequest?,
) {
setUserIdentity(mParticleUser)
}
override fun onUserIdentified(mParticleUser: MParticleUser?) {
- //Ignored
+ // Ignored
}
//endregion
//region Helpers
- private fun getApptentiveLogLevel(): LogLevel {
- return when (Logger.getMinLogLevel()) {
+ private fun getApptentiveLogLevel(): LogLevel =
+ when (Logger.getMinLogLevel()) {
MParticle.LogLevel.VERBOSE -> LogLevel.Verbose
MParticle.LogLevel.DEBUG -> LogLevel.Debug
MParticle.LogLevel.INFO -> LogLevel.Info
@@ -242,11 +260,10 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
MParticle.LogLevel.NONE -> LogLevel.Info
null -> LogLevel.Info
}
- }
private fun setUserIdentity(user: MParticleUser?) {
user?.userIdentities?.entries?.let {
- for(i in it.indices){
+ for (i in it.indices) {
val entry = it.elementAt(i)
when (entry.key) {
IdentityType.CustomerId -> {
@@ -266,12 +283,18 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
}
}
- private fun engage(event: String, customData: Map?) {
+ private fun engage(
+ event: String,
+ customData: Map?,
+ ) {
Apptentive.engage(event, parseCustomData(customData))
}
- /* Apptentive SDK does not provide a function which accepts Object as custom data so we need to cast */
- private fun addCustomPersonData(key: String, value: String) {
+ // Apptentive SDK does not provide a function which accepts Object as custom data so we need to cast
+ private fun addCustomPersonData(
+ key: String,
+ value: String,
+ ) {
// original key
Logger.debug("Adding custom person data $key to $value")
Apptentive.addCustomPersonData(key, value)
@@ -290,7 +313,7 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
}
else -> {
Logger.error(
- "Unexpected custom person data type:${typedValue?.javaClass}"
+ "Unexpected custom person data type:${typedValue?.javaClass}",
)
}
}
@@ -301,7 +324,6 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
if (map != null) {
val res: MutableMap = HashMap()
for ((key, value) in map) {
-
// original key
res[key] = value
@@ -319,7 +341,7 @@ class ApptentiveKit : KitIntegration(), KitIntegration.EventListener, IdentityLi
}
else -> {
Logger.error(
- "Unexpected custom data type:${typedValue?.javaClass}"
+ "Unexpected custom data type:${typedValue?.javaClass}",
)
}
}
diff --git a/src/main/kotlin/com/mparticle/kits/ApptentiveKitUtils.kt b/src/main/kotlin/com/mparticle/kits/ApptentiveKitUtils.kt
index 9043309..ecf7c81 100644
--- a/src/main/kotlin/com/mparticle/kits/ApptentiveKitUtils.kt
+++ b/src/main/kotlin/com/mparticle/kits/ApptentiveKitUtils.kt
@@ -14,24 +14,31 @@ import com.mparticle.internal.Logger
object ApptentiveKitUtils {
@JvmStatic
fun registerApptentiveActivityContext(callback: ApptentiveActivityInfo) {
- val broadcastReceiver = object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- if (intent.action?.startsWith(MParticle.ServiceProviders.BROADCAST_ACTIVE) == true) {
- Apptentive.registerApptentiveActivityInfoCallback(callback)
+ val broadcastReceiver =
+ object : BroadcastReceiver() {
+ override fun onReceive(
+ context: Context,
+ intent: Intent,
+ ) {
+ if (intent.action?.startsWith(MParticle.ServiceProviders.BROADCAST_ACTIVE) == true) {
+ Apptentive.registerApptentiveActivityInfoCallback(callback)
+ }
}
}
- }
if (MParticle.getInstance()?.isKitActive(MParticle.ServiceProviders.APPTENTIVE) == true) {
Apptentive.registerApptentiveActivityInfoCallback(callback)
Logger.debug("ApptentiveKitUtils", "registerApptentiveActivityContext: kit is active")
} else {
- val filter = IntentFilter(MParticle.ServiceProviders.BROADCAST_ACTIVE + MParticle.ServiceProviders.APPTENTIVE)
+ val filter =
+ IntentFilter(MParticle.ServiceProviders.BROADCAST_ACTIVE + MParticle.ServiceProviders.APPTENTIVE)
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.TIRAMISU) {
- callback.getApptentiveActivityInfo()
+ callback
+ .getApptentiveActivityInfo()
?.registerReceiver(broadcastReceiver, filter, RECEIVER_EXPORTED)
Logger.debug("ApptentiveKitUtils", "registerApptentiveActivityContext: SDK 33+")
} else {
- callback.getApptentiveActivityInfo()
+ callback
+ .getApptentiveActivityInfo()
?.registerReceiver(broadcastReceiver, filter)
Logger.debug("ApptentiveKitUtils", "registerApptentiveActivityContext: SDK < 33")
}
diff --git a/src/main/kotlin/com/mparticle/kits/CustomDataParser.kt b/src/main/kotlin/com/mparticle/kits/CustomDataParser.kt
index e29d614..94d1bfa 100644
--- a/src/main/kotlin/com/mparticle/kits/CustomDataParser.kt
+++ b/src/main/kotlin/com/mparticle/kits/CustomDataParser.kt
@@ -18,14 +18,13 @@ internal object CustomDataParser {
}
@JvmStatic
- fun parseValue(value: String?): Any? {
- return try {
+ fun parseValue(value: String?): Any? =
+ try {
if (value != null) parseValueGuarded(value) else null
} catch (e: Exception) {
Log.e(LogTag("pParticle"), "Unable to parse value: $value")
value
}
- }
private fun parseValueGuarded(value: String): Any {
// check for boolean
@@ -37,4 +36,4 @@ internal object CustomDataParser {
val number = StringUtils.tryParseNumber(value)
return number ?: value
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/mparticle/kits/StringUtils.kt b/src/main/kotlin/com/mparticle/kits/StringUtils.kt
index d483eae..11c8dbd 100644
--- a/src/main/kotlin/com/mparticle/kits/StringUtils.kt
+++ b/src/main/kotlin/com/mparticle/kits/StringUtils.kt
@@ -5,7 +5,7 @@ internal object StringUtils {
fun tryParseSettingFlag(
settings: Map,
key: String?,
- defaultValue: Boolean
+ defaultValue: Boolean,
): Boolean {
val value = settings[key]
return value?.toBoolean() ?: defaultValue
@@ -14,12 +14,13 @@ internal object StringUtils {
fun tryParseLongSettingFlag(
settings: Map,
key: String?,
- defaultValue: Long
+ defaultValue: Long,
): Long {
- val value = key?.let {
- settings[key]
- }
- return try {
+ val value =
+ key?.let {
+ settings[key]
+ }
+ return try {
value?.toLong() ?: defaultValue
} catch (e: NumberFormatException) {
defaultValue
@@ -30,27 +31,29 @@ internal object StringUtils {
fun tryParseNumber(value: String): Number? {
val longValue = tryParseLong(value)
return if (longValue != null) {
- if (isInIntegerRange(longValue)) longValue.toInt()
- else longValue
- } else tryParseDouble(value)
+ if (isInIntegerRange(longValue)) {
+ longValue.toInt()
+ } else {
+ longValue
+ }
+ } else {
+ tryParseDouble(value)
+ }
}
- private fun isInIntegerRange(value: Long): Boolean =
- value >= Int.MIN_VALUE && value <= Int.MAX_VALUE
+ private fun isInIntegerRange(value: Long): Boolean = value >= Int.MIN_VALUE && value <= Int.MAX_VALUE
- private fun tryParseLong(value: String): Long? {
- return try {
+ private fun tryParseLong(value: String): Long? =
+ try {
value.toLong()
} catch (e: NumberFormatException) {
null
}
- }
- private fun tryParseDouble(value: String): Double? {
- return try {
+ private fun tryParseDouble(value: String): Double? =
+ try {
value.toDouble()
} catch (e: NumberFormatException) {
null
}
- }
-}
\ No newline at end of file
+}
diff --git a/src/test/kotlin/com/mparticle/kits/ApptentiveKitTest.kt b/src/test/kotlin/com/mparticle/kits/ApptentiveKitTest.kt
index 74708a4..46645a9 100644
--- a/src/test/kotlin/com/mparticle/kits/ApptentiveKitTest.kt
+++ b/src/test/kotlin/com/mparticle/kits/ApptentiveKitTest.kt
@@ -1,18 +1,14 @@
package com.mparticle.kits
import android.content.Context
-import apptentive.com.android.core.Logger
import apptentive.com.android.feedback.Apptentive
import apptentive.com.android.util.InternalUseOnly
-import apptentive.com.android.util.Log
-import apptentive.com.android.util.LogTag
import com.mparticle.MParticle
import com.mparticle.MParticleOptions
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.verify
-import junit.framework.TestCase.*
import org.junit.Assert
import org.junit.Test
import org.mockito.Mockito
@@ -133,10 +129,11 @@ class ApptentiveKitTest {
@Test
fun testFullNameInTheUserAttributes() {
- val userAttributes = mutableMapOf(
- MParticle.UserAttributes.FIRSTNAME to "John",
- MParticle.UserAttributes.LASTNAME to "Doe"
- )
+ val userAttributes =
+ mutableMapOf(
+ MParticle.UserAttributes.FIRSTNAME to "John",
+ MParticle.UserAttributes.LASTNAME to "Doe",
+ )
val user = mockk()
mockkStatic(Apptentive::class)
@@ -152,10 +149,11 @@ class ApptentiveKitTest {
@Test
fun testListOfCustomPersonData() {
- val userAttributes = mutableMapOf(
- "key1" to "value1",
- "key2" to "20"
- )
+ val userAttributes =
+ mutableMapOf(
+ "key1" to "value1",
+ "key2" to "20",
+ )
val user = mockk()
mockkStatic(Apptentive::class)
every { Apptentive.addCustomPersonData(any(), any()) } returns Unit
diff --git a/src/test/kotlin/com/mparticle/kits/CustomDataParserTest.kt b/src/test/kotlin/com/mparticle/kits/CustomDataParserTest.kt
index 0428f9e..8f720ee 100644
--- a/src/test/kotlin/com/mparticle/kits/CustomDataParserTest.kt
+++ b/src/test/kotlin/com/mparticle/kits/CustomDataParserTest.kt
@@ -30,4 +30,4 @@ class CustomDataParserTest {
// string
Assert.assertEquals("test", parseValue("test"))
}
-}
\ No newline at end of file
+}
diff --git a/src/test/kotlin/com/mparticle/kits/StringUtilsTest.kt b/src/test/kotlin/com/mparticle/kits/StringUtilsTest.kt
index ef6118d..565906c 100644
--- a/src/test/kotlin/com/mparticle/kits/StringUtilsTest.kt
+++ b/src/test/kotlin/com/mparticle/kits/StringUtilsTest.kt
@@ -14,11 +14,11 @@ class StringUtilsTest {
Assert.assertEquals(Integer.valueOf(12345), tryParseNumber("12345") as Int?)
Assert.assertEquals(
java.lang.Long.valueOf(21474836479L),
- tryParseNumber("21474836479") as Long?
+ tryParseNumber("21474836479") as Long?,
)
Assert.assertEquals(
java.lang.Long.valueOf(-21474836489L),
- tryParseNumber("-21474836489") as Long?
+ tryParseNumber("-21474836489") as Long?,
)
Assert.assertEquals(java.lang.Double.valueOf(12345.0), tryParseNumber("12345.0") as Double?)
Assert.assertNull(tryParseNumber("test"))
@@ -26,36 +26,36 @@ class StringUtilsTest {
@Test
fun testSettingsFlag() {
- val data= HashMap()
+ val data = HashMap()
data["key"] = "true"
Assert.assertTrue(tryParseSettingFlag(data, "key", false))
}
@Test
fun testLongSettingFlag() {
- //key is not available
- var data= mapOf()
+ // key is not available
+ var data = mapOf()
val default = TimeUnit.DAYS.toMillis(7)
- Assert.assertEquals(default, tryParseLongSettingFlag(data, "key",default))
+ Assert.assertEquals(default, tryParseLongSettingFlag(data, "key", default))
- //key with a long value
+ // key with a long value
data = mapOf("key" to "500")
Assert.assertEquals(500L, tryParseLongSettingFlag(data, "key", default))
- //key with a invalid type
+ // key with a invalid type
data = mapOf("key" to "value")
Assert.assertEquals(default, tryParseLongSettingFlag(data, "key", default))
- //key that is not available in the map
+ // key that is not available in the map
Assert.assertEquals(default, tryParseLongSettingFlag(data, "key_1", default))
- //null key
+ // null key
Assert.assertEquals(default, tryParseLongSettingFlag(data, "null", default))
}
@Test
fun testMissingSettingsFlag() {
- val data= HashMap()
+ val data = HashMap()
Assert.assertFalse(tryParseSettingFlag(data, "key", false))
}
@@ -65,4 +65,4 @@ class StringUtilsTest {
data["key"] = "123"
Assert.assertFalse(tryParseSettingFlag(data, "key", false))
}
-}
\ No newline at end of file
+}