diff --git a/build.gradle b/build.gradle
index b0d4f57..9713aba 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,5 @@
-
buildscript {
- ext.kotlin_version = '1.7.22'
+ ext.kotlin_version = '2.0.20'
if (!project.hasProperty('version') || project.version.equals('unspecified')) {
project.version = '+'
}
@@ -10,16 +9,17 @@ 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:1.8.10'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
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,15 +31,25 @@ sonarqube {
}
apply plugin: 'org.jlleitschuh.gradle.ktlint'
-apply plugin: "kotlin-android"
+apply plugin: 'kotlin-android'
apply plugin: 'com.mparticle.kit'
android {
+ namespace 'com.mparticle.kits.button'
+ buildFeatures {
+ buildConfig = true
+ }
defaultConfig {
minSdkVersion 16
consumerProguardFiles 'consumer-proguard.pro'
}
-
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = '17'
+ }
testOptions {
unitTests.returnDefaultValues = true
unitTests.all {
@@ -49,9 +59,31 @@ android {
}
}
+repositories {
+ google()
+ mavenCentral()
+}
+
+configurations.all {
+ resolutionStrategy {
+ force "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ force "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ force "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+ force "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
+ // Force Kotlin compiler version to match stdlib
+ eachDependency { DependencyResolveDetails details ->
+ if (details.requested.group == 'org.jetbrains.kotlin' && details.requested.name.startsWith('kotlin-')) {
+ details.useVersion kotlin_version
+ }
+ }
+ }
+}
+
dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.annotation:annotation:1.5.0'
api 'com.usebutton.merchant:button-merchant:1.5.0'
testImplementation 'com.squareup.assertj:assertj-android:1.2.0'
- testImplementation ("io.mockk:mockk:1.13.4")
+ testImplementation "io.mockk:mockk-jvm:1.13.8"
}
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 cbe69af..c4e6c98 100755
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -1 +1 @@
-
+
diff --git a/src/main/kotlin/com/mparticle/kits/ButtonKit.kt b/src/main/kotlin/com/mparticle/kits/ButtonKit.kt
index fa0316c..f172a3f 100644
--- a/src/main/kotlin/com/mparticle/kits/ButtonKit.kt
+++ b/src/main/kotlin/com/mparticle/kits/ButtonKit.kt
@@ -12,21 +12,31 @@ import com.mparticle.commerce.CommerceEvent
import com.mparticle.commerce.Product
import com.mparticle.identity.MParticleUser
import com.mparticle.internal.Logger
-import com.mparticle.kits.KitIntegration.*
+import com.mparticle.kits.FilteredIdentityApiRequest
+import com.mparticle.kits.KitIntegration.ActivityListener
+import com.mparticle.kits.KitIntegration.CommerceListener
+import com.mparticle.kits.KitIntegration.IdentityListener
+import com.mparticle.kits.ReportingMessage
import com.usebutton.merchant.ButtonMerchant.AttributionTokenListener
import com.usebutton.merchant.ButtonProduct
import com.usebutton.merchant.ButtonProductCompatible
import com.usebutton.merchant.PostInstallIntentListener
import java.math.BigDecimal
-import java.util.*
+import java.util.ArrayList
+import java.util.Collections
/**
* MParticle embedded implementation of the [Button Merchant Library](https://github.com/button/button-merchant-android).
*
* Learn more at our [Developer Docs](https://developer.usebutton.com/guides/merchants/android/button-merchant-integration-guide)
*/
-class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, IdentityListener,
- AttributionTokenListener, PostInstallIntentListener {
+class ButtonKit :
+ KitIntegration(),
+ ActivityListener,
+ CommerceListener,
+ IdentityListener,
+ AttributionTokenListener,
+ PostInstallIntentListener {
private var applicationContext: Context? = null
@JvmField
@@ -39,7 +49,7 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
public override fun onKitCreate(
settings: Map,
- ctx: Context
+ ctx: Context,
): List {
applicationContext = ctx.applicationContext
val applicationId = settings[APPLICATION_ID]
@@ -50,7 +60,6 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
throwOnKitCreateError(LOWER_THAN_API_15)
}
applicationContext?.let {
-
if (applicationId != null) {
merchant.configure(it, applicationId)
}
@@ -69,6 +78,7 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
/*
* Public methods to expose important Merchant Library methods
*/
+
/**
* Get the Button attribution token which should be attached to any orders reported and
* attributed to the Button network.
@@ -90,7 +100,7 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
* // Use token with your order reporting.
* }
* }
- *
+ *
*
* @return the last tracked Button attribution token.
*/
@@ -104,20 +114,25 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
logDebug("Refreshed Button Attribution Token: %s", token)
}
- override fun onResult(intent: Intent?, throwable: Throwable?) {
+ override fun onResult(
+ intent: Intent?,
+ throwable: Throwable?,
+ ) {
val pm = applicationContext?.packageManager
if (pm?.let { intent?.resolveActivity(it) } != null) {
logDebug("Handling post-install intent for %s", intent.toString())
- val result = AttributionResult()
- .setLink(intent?.dataString)
- .setServiceProviderId(configuration.kitId)
+ val result =
+ AttributionResult()
+ .setLink(intent?.dataString)
+ .setServiceProviderId(configuration.kitId)
kitManager.onResult(result)
}
if (throwable != null) {
logError("Error checking post install intent", throwable)
- val attributionError = AttributionError()
- .setMessage(throwable.message)
- .setServiceProviderId(configuration.kitId)
+ val attributionError =
+ AttributionError()
+ .setMessage(throwable.message)
+ .setServiceProviderId(configuration.kitId)
kitManager.onError(attributionError)
}
}
@@ -125,7 +140,10 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
/*
* Overrides for ActivityListener
*/
- override fun onActivityCreated(activity: Activity, bundle: Bundle?): List {
+ override fun onActivityCreated(
+ activity: Activity,
+ bundle: Bundle?,
+ ): List {
applicationContext?.let { merchant.trackIncomingIntent(it, activity.intent) }
return emptyList()
}
@@ -144,21 +162,21 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
override fun onActivityStopped(activity: Activity): List = emptyList()
-
override fun onActivitySaveInstanceState(
activity: Activity,
- bundle: Bundle?
+ bundle: Bundle?,
): List = emptyList()
override fun onActivityDestroyed(activity: Activity): List = emptyList()
-
/*
* Overrides for CommerceListener
*/
override fun logLtvIncrease(
- bigDecimal: BigDecimal, bigDecimal1: BigDecimal,
- s: String, map: Map
+ bigDecimal: BigDecimal,
+ bigDecimal1: BigDecimal,
+ s: String,
+ map: Map,
): List = emptyList()
override fun logEvent(commerceEvent: CommerceEvent): List {
@@ -182,10 +200,11 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
logDebug("Tracking cart viewed with %d products!", products.size)
merchant.trackCartViewed(products)
}
- else -> logDebug(
- "Product Action [%s] is not yet supported by the Button Merchant Library",
- it
- )
+ else ->
+ logDebug(
+ "Product Action [%s] is not yet supported by the Button Merchant Library",
+ it,
+ )
}
}
return emptyList()
@@ -196,26 +215,26 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
*/
override fun onIdentifyCompleted(
mParticleUser: MParticleUser,
- filteredIdentityApiRequest: FilteredIdentityApiRequest
+ filteredIdentityApiRequest: FilteredIdentityApiRequest,
) {
}
override fun onLoginCompleted(
mParticleUser: MParticleUser,
- filteredIdentityApiRequest: FilteredIdentityApiRequest
+ filteredIdentityApiRequest: FilteredIdentityApiRequest,
) {
}
override fun onLogoutCompleted(
mParticleUser: MParticleUser,
- filteredIdentityApiRequest: FilteredIdentityApiRequest
+ filteredIdentityApiRequest: FilteredIdentityApiRequest,
) {
merchant.clearAllData(applicationContext!!)
}
override fun onModifyCompleted(
mParticleUser: MParticleUser,
- filteredIdentityApiRequest: FilteredIdentityApiRequest
+ filteredIdentityApiRequest: FilteredIdentityApiRequest,
) {
}
@@ -224,17 +243,21 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
/*
* Utility methods
*/
- private fun logDebug(message: String, vararg args: Any) {
+ private fun logDebug(
+ message: String,
+ vararg args: Any,
+ ) {
Logger.debug(String.format("ButtonKit: $message", *args))
}
- private fun logError(message: String, t: Throwable) {
+ private fun logError(
+ message: String,
+ t: Throwable,
+ ) {
Logger.error(t, "ButtonKit: $message")
}
- private fun throwOnKitCreateError(message: String) {
- throw IllegalArgumentException(message)
- }
+ private fun throwOnKitCreateError(message: String): Unit = throw IllegalArgumentException(message)
private fun parseAsButtonProducts(products: List?): List {
val buttonProducts: MutableList = ArrayList()
@@ -247,7 +270,7 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
private fun parseAsButtonProduct(
product: Product?,
- collectionSize: Int
+ collectionSize: Int,
): ButtonProductCompatible {
val buttonProduct = ButtonProduct()
if (product == null) return buttonProduct
@@ -256,10 +279,11 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
buttonProduct.value = (product.totalAmount * 100).toInt()
buttonProduct.quantity = product.quantity.toInt()
buttonProduct.categories = listOf(product.category)
- buttonProduct.attributes = Collections.singletonMap(
- "btn_product_count",
- collectionSize.toString()
- )
+ buttonProduct.attributes =
+ Collections.singletonMap(
+ "btn_product_count",
+ collectionSize.toString(),
+ )
return buttonProduct
}
@@ -271,4 +295,4 @@ class ButtonKit : KitIntegration(), ActivityListener, CommerceListener, Identity
const val LOWER_THAN_API_15 =
"App running in an < API 15 environment, can't initialize kit."
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/mparticle/kits/ButtonMerchantWrapper.kt b/src/main/kotlin/com/mparticle/kits/ButtonMerchantWrapper.kt
index 39b86a1..b0aad2c 100644
--- a/src/main/kotlin/com/mparticle/kits/ButtonMerchantWrapper.kt
+++ b/src/main/kotlin/com/mparticle/kits/ButtonMerchantWrapper.kt
@@ -1,33 +1,43 @@
package com.mparticle.kits
import android.content.Context
-import com.usebutton.merchant.ButtonMerchant
import android.content.Intent
+import com.usebutton.merchant.ButtonMerchant
import com.usebutton.merchant.ButtonMerchant.AttributionTokenListener
-import com.usebutton.merchant.PostInstallIntentListener
import com.usebutton.merchant.ButtonProductCompatible
+import com.usebutton.merchant.PostInstallIntentListener
/**
* Wrapper class for [ButtonMerchant] to allow for testing the library's static methods
*/
class ButtonMerchantWrapper {
- fun configure(context: Context, applicationId: String) {
+ fun configure(
+ context: Context,
+ applicationId: String,
+ ) {
ButtonMerchant.configure(context, applicationId)
}
- fun trackIncomingIntent(context: Context, intent: Intent) {
+ fun trackIncomingIntent(
+ context: Context,
+ intent: Intent,
+ ) {
ButtonMerchant.trackIncomingIntent(context, intent)
}
- fun getAttributionToken(context: Context): String? {
- return ButtonMerchant.getAttributionToken(context)
- }
+ fun getAttributionToken(context: Context): String? = ButtonMerchant.getAttributionToken(context)
- fun addAttributionTokenListener(context: Context, listener: AttributionTokenListener) {
+ fun addAttributionTokenListener(
+ context: Context,
+ listener: AttributionTokenListener,
+ ) {
ButtonMerchant.addAttributionTokenListener(context, listener)
}
- fun handlePostInstallIntent(context: Context, listener: PostInstallIntentListener) {
+ fun handlePostInstallIntent(
+ context: Context,
+ listener: PostInstallIntentListener,
+ ) {
ButtonMerchant.handlePostInstallIntent(context, listener)
}
@@ -46,4 +56,4 @@ class ButtonMerchantWrapper {
fun trackCartViewed(products: List) {
ButtonMerchant.activity().cartViewed(products)
}
-}
\ No newline at end of file
+}
diff --git a/src/test/kotlin/com/mparticle/kits/ButtonKitTests.kt b/src/test/kotlin/com/mparticle/kits/ButtonKitTests.kt
index 2e40c46..d9a319e 100644
--- a/src/test/kotlin/com/mparticle/kits/ButtonKitTests.kt
+++ b/src/test/kotlin/com/mparticle/kits/ButtonKitTests.kt
@@ -20,7 +20,11 @@ import com.mparticle.identity.MParticleUser
import com.mparticle.internal.CoreCallbacks
import com.mparticle.internal.CoreCallbacks.KitListener
import com.usebutton.merchant.ButtonProductCompatible
-import io.mockk.*
+import io.mockk.Called
+import io.mockk.every
+import io.mockk.mockk
+import io.mockk.slot
+import io.mockk.verify
import org.assertj.core.api.Assertions.assertThat
import org.json.JSONArray
import org.junit.Assert
@@ -32,8 +36,8 @@ import org.mockito.Mockito.`when`
import java.lang.ref.WeakReference
import java.lang.reflect.Field
import java.lang.reflect.Modifier
-import java.util.*
-
+import java.util.Collections
+import java.util.HashMap
class ButtonKitTests {
private val context = mockk(relaxed = true)
@@ -197,11 +201,13 @@ class ButtonKitTests {
fun logEvent_shouldConvertToButtonProduct() {
val productCaptor = slot()
- val product = Product.Builder("Test Name", "98765", 12.34)
- .category("Test category")
- .quantity(2.0)
- .customAttributes(Collections.singletonMap("test_key", "test_value"))
- .build()
+ val product =
+ Product
+ .Builder("Test Name", "98765", 12.34)
+ .category("Test category")
+ .quantity(2.0)
+ .customAttributes(Collections.singletonMap("test_key", "test_value"))
+ .build()
val event = CommerceEvent.Builder(Product.DETAIL, product).build()
buttonKit.logEvent(event)
@@ -247,7 +253,6 @@ class ButtonKitTests {
}
buttonKit.logEvent(eventBuilder.build())
verify(exactly = 1) { (merchant).trackAddToCart(any()) }
-
}
@Test
@@ -258,37 +263,41 @@ class ButtonKitTests {
for (i in 0..19) {
eventBuilder.addProduct(product)
}
- println(eventBuilder.build().products?.size.toString())
+ println(
+ eventBuilder
+ .build()
+ .products
+ ?.size
+ .toString(),
+ )
buttonKit.logEvent(eventBuilder.build())
- verify (exactly = 1){ (merchant).trackCartViewed(capture(listCaptor)) }
+ verify(exactly = 1) { (merchant).trackCartViewed(capture(listCaptor)) }
assertThat(listCaptor.captured.size).isEqualTo(21)
}
-
private inner class TestKitManager internal constructor() :
KitManagerImpl(context, null, TestCoreCallbacks(), mock(MParticleOptions::class.java)) {
- var attributes = HashMap()
- var result: AttributionResult? = null
- private var error: AttributionError? = null
- public override fun getIntegrationAttributes(kitIntegration: KitIntegration): Map {
- return attributes
- }
+ var attributes = HashMap()
+ var result: AttributionResult? = null
+ private var error: AttributionError? = null
- public override fun setIntegrationAttributes(
- kitIntegration: KitIntegration,
- integrationAttributes: Map
- ) {
- attributes = integrationAttributes as HashMap
- }
+ public override fun getIntegrationAttributes(kitIntegration: KitIntegration): Map = attributes
- override fun onResult(result: AttributionResult) {
- this.result = result
- }
+ public override fun setIntegrationAttributes(
+ kitIntegration: KitIntegration,
+ integrationAttributes: Map,
+ ) {
+ attributes = integrationAttributes as HashMap
+ }
+
+ override fun onResult(result: AttributionResult) {
+ this.result = result
+ }
- override fun onError(error: AttributionError) {
- this.error = error
+ override fun onError(error: AttributionError) {
+ this.error = error
+ }
}
- }
private inner class TestKitConfiguration : KitConfiguration() {
override fun getKitId(): Int = TEST_KIT_ID
@@ -296,36 +305,69 @@ class ButtonKitTests {
private inner class TestMParticle : MParticle() {
override fun Identity(): IdentityApi = mock(IdentityApi::class.java)
-
}
internal inner class TestCoreCallbacks : CoreCallbacks {
override fun isBackgrounded(): Boolean = false
+
override fun getUserBucket(): Int = 0
+
override fun isEnabled(): Boolean = false
- override fun setIntegrationAttributes(i: Int, map: Map) {}
+
+ override fun setIntegrationAttributes(
+ i: Int,
+ map: Map,
+ ) {}
+
override fun getIntegrationAttributes(i: Int): Map? = null
+
override fun getCurrentActivity(): WeakReference? = null
+
override fun getLatestKitConfiguration(): JSONArray? = null
+
override fun getDataplanOptions(): DataplanOptions? = null
+
override fun isPushEnabled(): Boolean = false
+
override fun getPushSenderId(): String? = null
+
override fun getPushInstanceId(): String? = null
+
override fun getLaunchUri(): Uri? = null
+
override fun getLaunchAction(): String? = null
- override fun getKitListener(): KitListener {
- return object : KitListener {
+
+ override fun getKitListener(): KitListener =
+ object : KitListener {
override fun kitFound(kitId: Int) {}
- override fun kitConfigReceived(kitId: Int, configuration: String?) {}
- override fun kitExcluded(kitId: Int, reason: String?) {}
+
+ override fun kitConfigReceived(
+ kitId: Int,
+ configuration: String?,
+ ) {}
+
+ override fun kitExcluded(
+ kitId: Int,
+ reason: String?,
+ ) {}
+
override fun kitStarted(kitId: Int) {}
- override fun onKitApiCalled(kitId: Int, used: Boolean?, vararg objects: Any?) {
+
+ override fun onKitApiCalled(
+ kitId: Int,
+ used: Boolean?,
+ vararg objects: Any?,
+ ) {
}
- override fun onKitApiCalled(methodName: String?, kitId: Int, used: Boolean?, vararg objects: Any?) {
+ override fun onKitApiCalled(
+ methodName: String?,
+ kitId: Int,
+ used: Boolean?,
+ vararg objects: Any?,
+ ) {
}
}
- }
}
companion object {
@@ -335,20 +377,23 @@ class ButtonKitTests {
private const val TEST_KIT_ID = 0x01
/*
- * Test Helpers
- */
+ * Test Helpers
+ */
@Throws(Exception::class)
private fun setTestSdkVersion(sdkVersion: Int) {
setFinalStatic(VERSION::class.java.getField("SDK_INT"), sdkVersion)
}
@Throws(Exception::class)
- private fun setFinalStatic(field: Field, newValue: Int) {
+ private fun setFinalStatic(
+ field: Field,
+ newValue: Int,
+ ) {
field.isAccessible = true
val getDeclaredFields0 =
Class::class.java.getDeclaredMethod(
"getDeclaredFields0",
- Boolean::class.javaPrimitiveType
+ Boolean::class.javaPrimitiveType,
)
getDeclaredFields0.isAccessible = true
val fields = getDeclaredFields0.invoke(Field::class.java, false) as Array
@@ -362,8 +407,6 @@ class ButtonKitTests {
modifiersField!!.isAccessible = true
modifiersField!!.setInt(field, field.modifiers and Modifier.FINAL.inv())
field[null] = newValue
-
}
-
}
-}
\ No newline at end of file
+}