Skip to content

Commit

Permalink
feat: sdk 1954 misc issues remove external ids and collect ad (#442)
Browse files Browse the repository at this point in the history
fix: collecting ad id. executor was missing for ad collection
fix: external ids are only sent for identify events, removed from any other events.
chore: enable ad id in sample app
  • Loading branch information
itsdebs authored Jun 18, 2024
1 parent 6781895 commit cb3b826
Show file tree
Hide file tree
Showing 24 changed files with 566 additions and 356 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ package com.rudderstack.android
import android.app.Application
import androidx.annotation.RestrictTo
import com.rudderstack.android.internal.AndroidLogger
import com.rudderstack.android.storage.AndroidStorage
import com.rudderstack.android.storage.AndroidStorageImpl
import com.rudderstack.core.Base64Generator
import com.rudderstack.core.Configuration
import com.rudderstack.core.Logger
import com.rudderstack.core.RetryStrategy
import com.rudderstack.core.RudderOptions
import com.rudderstack.core.Storage
import com.rudderstack.core.RudderOption
import com.rudderstack.rudderjsonadapter.JsonAdapter
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
Expand Down Expand Up @@ -86,7 +83,7 @@ interface ConfigurationAndroid : Configuration {
jsonAdapter: JsonAdapter,
anonymousId: String?= null,
userId: String? = null,
options: RudderOptions = RudderOptions.defaultOptions(),
options: RudderOption = RudderOption(),
flushQueueSize: Int = Defaults.DEFAULT_FLUSH_QUEUE_SIZE,
maxFlushInterval: Long = Defaults.DEFAULT_MAX_FLUSH_INTERVAL,
shouldVerifySdk: Boolean = Defaults.SHOULD_VERIFY_SDK,
Expand All @@ -105,7 +102,7 @@ interface ConfigurationAndroid : Configuration {
logger: Logger = AndroidLogger,
analyticsExecutor: ExecutorService = Executors.newSingleThreadExecutor(),
networkExecutor: ExecutorService = Executors.newCachedThreadPool(),
advertisingIdFetchExecutor : ExecutorService? = null,
advertisingIdFetchExecutor : ExecutorService? = Executors.newCachedThreadPool(),
base64Generator: Base64Generator = AndroidUtils.defaultBase64Generator(),
trackAutoSession: Boolean = Defaults.AUTO_SESSION_TRACKING,
sessionTimeoutMillis: Long = Defaults.SESSION_TIMEOUT
Expand All @@ -129,7 +126,7 @@ interface ConfigurationAndroid : Configuration {
override val trackAutoSession: Boolean = trackAutoSession
override val sessionTimeoutMillis: Long = sessionTimeoutMillis
override val jsonAdapter: JsonAdapter = jsonAdapter
override val options: RudderOptions = options
override val options: RudderOption = options
override val flushQueueSize: Int = flushQueueSize
override val maxFlushInterval: Long = maxFlushInterval
override val shouldVerifySdk: Boolean = shouldVerifySdk
Expand Down Expand Up @@ -202,7 +199,7 @@ interface ConfigurationAndroid : Configuration {

override fun copy(
jsonAdapter: JsonAdapter,
options: RudderOptions,
options: RudderOption,
flushQueueSize: Int,
maxFlushInterval: Long,
shouldVerifySdk: Boolean,
Expand Down Expand Up @@ -235,7 +232,7 @@ interface ConfigurationAndroid : Configuration {

fun copy(
jsonAdapter: JsonAdapter = this.jsonAdapter,
options: RudderOptions = this.options,
options: RudderOption = this.options,
flushQueueSize: Int = this.flushQueueSize,
maxFlushInterval: Long = this.maxFlushInterval,
shouldVerifySdk: Boolean = this.shouldVerifySdk,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.rudderstack.models.AliasMessage
import com.rudderstack.models.IdentifyMessage
import com.rudderstack.models.Message
import com.rudderstack.models.MessageContext
import com.rudderstack.models.optAddContext
import com.rudderstack.models.traits
import com.rudderstack.models.updateWith

Expand Down Expand Up @@ -80,10 +81,13 @@ internal class ExtractStatePlugin : Plugin {
}
}
is IdentifyMessage -> {
if(newUserId != prevId) {
replaceContext(it)
} else appendContext(it)
message
val updatedContext = if(newUserId != prevId) {
it
} else {
appendContextForIdentify(it)
}
replaceContext(updatedContext)
message.copy(context = updatedContext)
}
else -> {
message
Expand All @@ -99,8 +103,10 @@ internal class ExtractStatePlugin : Plugin {
}
}

private fun appendContext(messageContext: MessageContext) {
_analytics?.processNewContext( messageContext optAdd _analytics?.contextState?.value)
private fun appendContextForIdentify(messageContext: MessageContext) : MessageContext{
return _analytics?.contextState?.value?.let {
messageContext optAddContext it
}?: messageContext
}

private fun replaceContext(messageContext: MessageContext) {
Expand Down Expand Up @@ -150,7 +156,6 @@ internal class ExtractStatePlugin : Plugin {
const val CONTEXT_USER_ID_KEY = "user_id"
const val CONTEXT_USER_ID_KEY_ALIAS = "userId"
const val CONTEXT_ID_KEY = "id"
const val CONTEXT_EXTERNAL_ID_KEY = "externalIds"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,21 @@ internal class FillDefaultsPlugin : Plugin {
throw ex
}
//copying top level context to message context

return (this.copy(context = (
val newContext =
// in case of alias we purposefully remove traits from context
_analytics?.contextState?.value?.let {
if (this is AliasMessage && this.userId != _analytics?.currentConfigurationAndroid?.userId) it.updateWith(
traits = mapOf()
) else it
} selectiveReplace context),
} selectiveReplace context.let {
if (this !is IdentifyMessage) {
// remove any external ids present in the message
// this is in accordance to v1
it?.withExternalIdsRemoved()
} else it
}

return (this.copy(context = newContext,
anonymousId = anonId,
userId = userId) as T)
}
Expand All @@ -78,28 +85,6 @@ internal class FillDefaultsPlugin : Plugin {
return this.updateWith(context)
}

private infix fun MessageContext?.optAdd(context: MessageContext?): MessageContext? {
//this gets priority
if (this == null) return context
else if (context == null) return this
val newTraits = context.traits?.let {
(it - (this.traits?.keys ?: setOf()).toSet()) optAdd this.traits
} ?: traits
val newCustomContexts = context.customContexts?.let {
(it - (this.customContexts?.keys ?: setOf()).toSet()) optAdd this.customContexts
} ?: customContexts
val newExternalIds = context.externalIds?.let {
(it minusWrtKeys (this.externalIds ?: listOf())) + it
} ?: externalIds

createContext(newTraits, newExternalIds, newCustomContexts).let {
//add the extra info from both contexts
val extraThisContext = this - it.keys
val extraOperandContext = context - it.keys
return it + extraThisContext + extraOperandContext
}
}

override fun intercept(chain: Plugin.Chain): Message {
val message = chain.message().withDefaults()
return chain.proceed(message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import android.os.Build
import android.provider.Settings
import android.telephony.TelephonyManager
import com.rudderstack.android.AndroidUtils
import com.rudderstack.android.AndroidUtils.isOnClassPath
import com.rudderstack.android.AndroidUtils.isTv
import com.rudderstack.android.LifecycleListenerPlugin
import com.rudderstack.android.utilities.currentConfigurationAndroid
Expand All @@ -39,10 +40,9 @@ import java.util.concurrent.atomic.AtomicReference
/**
* Sets the context specific to Android
*
* @property application The application is needed to generate the required values
* @constructor
* Initiates the values
*
* @constructor Initiates the values
* @property application The application is needed to generate the required
* values
*/
private const val CHANNEL = "mobile"

Expand Down Expand Up @@ -108,8 +108,24 @@ internal class PlatformInputsPlugin : Plugin, LifecycleListenerPlugin {
}

private fun Application.collectAdvertisingId() {
if(!isOnClassPath("com.google.android.gms.ads.identifier.AdvertisingIdClient")){
_analytics?.currentConfiguration?.logger?.debug(log = "Not collecting advertising ID because "
+ "com.google.android.gms.ads.identifier.AdvertisingIdClient "
+ "was not found on the classpath."
)
return
}
_analytics?.currentConfigurationAndroid?.advertisingIdFetchExecutor?.submit {
val adId = getGooglePlayServicesAdvertisingID() ?: getAmazonFireAdvertisingID()
val adId = try {
getGooglePlayServicesAdvertisingID()
} catch (ex: Exception) {
_analytics?.currentConfiguration?.logger?.error(log = "Error collecting play services ad id", throwable = ex)
null
} ?: try { getAmazonFireAdvertisingID() } catch (ex: Exception){
_analytics?.currentConfiguration?.logger?.error(log = "Error collecting amazon fire ad id", throwable = ex)
null
}
_analytics?.currentConfiguration?.logger?.info(log = "Ad id collected is $adId")
if (adId != null) {
synchronized(this) {
_advertisingId = adId
Expand Down Expand Up @@ -279,6 +295,7 @@ internal class PlatformInputsPlugin : Plugin, LifecycleListenerPlugin {

override fun onShutDown() {
super.onShutDown()
_analytics?.currentConfigurationAndroid?.advertisingIdFetchExecutor?.shutdownNow()
_analytics = null
}

Expand Down
Loading

0 comments on commit cb3b826

Please sign in to comment.