diff --git a/README.md b/README.md index 473026306..afd57f5f9 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,7 @@ This is the official Customer.io SDK for Android. -You'll find our [complete SDK documentation at https://customer.io/docs/sdk/android](https://customer.io/docs/sdk/android/). This readme only contains basic information to help you install and initialize the SDK. - -**Our SDK is a work in progress!** While we're *very* excited about it, it's still in its alpha phase; it is not ready for general availability. If you want to try it out, contact [product@customer.io](mailto:product@customer.io) and we'll help set you up! - -## Summary +# Getting started The SDK supports both Kotlin and Java. diff --git a/app/src/main/java/io/customer/example/MainActivity.kt b/app/src/main/java/io/customer/example/MainActivity.kt index 932ae3d23..d0df75419 100644 --- a/app/src/main/java/io/customer/example/MainActivity.kt +++ b/app/src/main/java/io/customer/example/MainActivity.kt @@ -48,11 +48,15 @@ class MainActivity : AppCompatActivity() { ).enqueue(outputCallback) CustomerIO.instance().track( name = "int event", - attributes = mapOf("value" to 1) + attributes = mapOf("value" to 1388377266772) ).enqueue(outputCallback) CustomerIO.instance().track( name = "long event", - attributes = mapOf("value" to 1L) + attributes = mapOf("value" to 1653L) + ).enqueue(outputCallback) + CustomerIO.instance().track( + name = "double event", + attributes = mapOf("value" to 133333.882) ).enqueue(outputCallback) CustomerIO.instance().track( name = "array event", @@ -87,9 +91,10 @@ class MainActivity : AppCompatActivity() { CoroutineScope(Dispatchers.IO).launch { when ( val result = - CustomerIO.instance() - .identify("sample@email.com@email.com", mapOf("speed" to "slow")) - .execute() + CustomerIO.instance().identify( + identifier = "support-ticket-test", + mapOf("created_at" to 1642659790) + ).execute() ) { is ErrorResult -> Log.v("ErrorResult", result.error.cause.toString()) is Success -> Log.v("Success", "Success") diff --git a/sdk/src/main/java/io/customer/sdk/data/moshi/CustomerIOParser.kt b/sdk/src/main/java/io/customer/sdk/data/moshi/CustomerIOParser.kt index baeba8345..ce4e701d2 100644 --- a/sdk/src/main/java/io/customer/sdk/data/moshi/CustomerIOParser.kt +++ b/sdk/src/main/java/io/customer/sdk/data/moshi/CustomerIOParser.kt @@ -3,6 +3,7 @@ package io.customer.sdk.data.moshi import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import io.customer.sdk.data.moshi.adapter.BigDecimalAdapter import io.customer.sdk.data.moshi.adapter.SupportedAttributesFactory internal interface CustomerIOParser { @@ -14,6 +15,7 @@ internal class CustomerIOParserImpl : CustomerIOParser { private val moshi by lazy { Moshi.Builder() + .add(BigDecimalAdapter()) .add(SupportedAttributesFactory()) .build() } diff --git a/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/BigDecimalAdapter.kt b/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/BigDecimalAdapter.kt new file mode 100644 index 000000000..bb5928282 --- /dev/null +++ b/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/BigDecimalAdapter.kt @@ -0,0 +1,13 @@ +package io.customer.sdk.data.moshi.adapter + +import com.squareup.moshi.FromJson +import com.squareup.moshi.ToJson +import java.math.BigDecimal + +class BigDecimalAdapter { + @FromJson + fun fromJson(string: String) = BigDecimal(string) + + @ToJson + fun toJson(value: BigDecimal) = value.toString() +} diff --git a/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/SupportedAttributesAdapter.kt b/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/SupportedAttributesAdapter.kt index ede554587..42707d73a 100644 --- a/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/SupportedAttributesAdapter.kt +++ b/sdk/src/main/java/io/customer/sdk/data/moshi/adapter/SupportedAttributesAdapter.kt @@ -2,6 +2,7 @@ package io.customer.sdk.data.moshi.adapter import com.squareup.moshi.* import java.lang.reflect.Type +import java.math.BigDecimal internal class SupportedAttributesFactory : JsonAdapter.Factory { override fun create( @@ -20,6 +21,8 @@ internal class SupportedAttributesAdapter(moshi: Moshi) : JsonAdapter>() { private val elementAdapter: JsonAdapter = moshi.adapter(Any::class.java) + private val elementBigDecimalAdapter: JsonAdapter = + moshi.adapter(BigDecimal::class.java) private val mapAdapter: JsonAdapter> = moshi.adapter( @@ -37,7 +40,11 @@ internal class SupportedAttributesAdapter(moshi: Moshi) : try { val name = reader.nextName() val peeked = reader.peekJson() - result[name] = elementAdapter.fromJson(peeked)!! + if (peeked.peek() == JsonReader.Token.NUMBER) { + result[name] = elementBigDecimalAdapter.fromJson(peeked)!! + } else { + result[name] = elementAdapter.fromJson(peeked)!! + } } catch (ignored: JsonDataException) { } reader.skipValue() diff --git a/sdk/src/main/java/io/customer/sdk/di/CustomerIOComponent.kt b/sdk/src/main/java/io/customer/sdk/di/CustomerIOComponent.kt index a2e74cb15..101a49df7 100644 --- a/sdk/src/main/java/io/customer/sdk/di/CustomerIOComponent.kt +++ b/sdk/src/main/java/io/customer/sdk/di/CustomerIOComponent.kt @@ -1,6 +1,7 @@ package io.customer.sdk.di import android.content.Context +import com.squareup.moshi.Moshi import io.customer.sdk.BuildConfig import io.customer.sdk.CustomerIOClient import io.customer.sdk.CustomerIOConfig @@ -12,6 +13,7 @@ import io.customer.sdk.api.service.CustomerService import io.customer.sdk.api.service.PushService import io.customer.sdk.data.moshi.CustomerIOParser import io.customer.sdk.data.moshi.CustomerIOParserImpl +import io.customer.sdk.data.moshi.adapter.BigDecimalAdapter import io.customer.sdk.data.store.* import io.customer.sdk.repository.* import okhttp3.OkHttpClient @@ -88,6 +90,14 @@ internal class CustomerIOComponent( } } + private val retrofitMoshiConverterFactory by lazy { + MoshiConverterFactory.create( + Moshi.Builder() + .add(BigDecimalAdapter()) + .build() + ) + } + private fun buildRetrofit( endpoint: String, timeout: Long @@ -96,7 +106,7 @@ internal class CustomerIOComponent( return Retrofit.Builder() .baseUrl(endpoint) .client(okHttpClient) - .addConverterFactory(MoshiConverterFactory.create()) + .addConverterFactory(retrofitMoshiConverterFactory) .addCallAdapterFactory(CustomerIoCallAdapterFactory.create()) .build() } diff --git a/sdk/src/test/java/io/customer/sdk/repositories/AttributesRepositoryTest.kt b/sdk/src/test/java/io/customer/sdk/repositories/AttributesRepositoryTest.kt index 30b359e52..a2f010383 100644 --- a/sdk/src/test/java/io/customer/sdk/repositories/AttributesRepositoryTest.kt +++ b/sdk/src/test/java/io/customer/sdk/repositories/AttributesRepositoryTest.kt @@ -35,16 +35,18 @@ internal class AttributesRepositoryTest { val result = attributesRepository.mapToJson(mapOf("key" to 1, "key2" to 2)) // JSON only has numbers. Not integers or doubles. And since numbers can have decimals they are always represented as doubles in Java. - val expected = mapOf("key" to 1, "key2" to 2).mapValues { it.value.toDouble() } + val expected = mapOf("key" to 1, "key2" to 2).mapValues { it.value.toBigDecimal() } (result == expected).shouldBeTrue() } @Test fun `Verify Long attributes are mapped correctly`() { - val expected = mapOf("key" to 1.0, "key2" to 2.0) + val expected = + sortedMapOf("key" to 1.0, "key2" to 2.0).mapValues { it.value.toBigDecimal() } - val result = attributesRepository.mapToJson(mapOf("key" to 1.0, "key2" to 2.0)) + val result = + attributesRepository.mapToJson(mutableMapOf("key" to 1.0, "key2" to 2.0)).toSortedMap() (result == expected).shouldBeTrue() } @@ -53,7 +55,7 @@ internal class AttributesRepositoryTest { fun `Verify Date attributes are mapped correctly`() { val date = Date() - val expected = mapOf("key" to date.getUnixTimestamp().toDouble()) + val expected = mapOf("key" to date.getUnixTimestamp().toBigDecimal()) // even if Date is sent, unix timestamp should be mapped val result = attributesRepository.mapToJson(mapOf("key" to date))