Skip to content

Commit

Permalink
Merge branch 'release/6.0.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
matus-tomlein committed Feb 29, 2024
2 parents bc58421 + be0ecd8 commit c1be49c
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 73 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Version 6.0.2 (2024-02-28)
--------------------------
Fix createTracker call hanging for 10 seconds if run on a background thread (#620)

Version 6.0.1 (2024-02-14)
--------------------------
Fix wrong screen entity info assigned for screen end event and in case events are tracked right before screen view (#673)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.1
6.0.2
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ plugins {

subprojects {
group = 'com.snowplowanalytics'
version = '6.0.1'
version = '6.0.2'
repositories {
google()
maven {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ systemProp.org.gradle.internal.http.socketTimeout=120000
SONATYPE_STAGING_PROFILE=comsnowplowanalytics
GROUP=com.snowplowanalytics
POM_ARTIFACT_ID=snowplow-android-tracker
VERSION_NAME=6.0.1
VERSION_NAME=6.0.2

POM_NAME=snowplow-android-tracker
POM_PACKAGING=aar
Expand Down
1 change: 1 addition & 0 deletions snowplow-demo-kotlin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ dependencies {
implementation 'androidx.browser:browser:1.5.0'
implementation 'com.google.android.gms:play-services-appset:16.0.2'
implementation "com.android.installreferrer:installreferrer:2.2"
implementation "com.google.android.gms:play-services-ads:22.6.0"
}
5 changes: 5 additions & 0 deletions snowplow-demo-kotlin/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- Enable the permissions below for getting users geographical location. -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>

<application
android:allowBackup="true"
Expand Down Expand Up @@ -33,6 +34,10 @@
android:name=".Demo"
android:label="@string/title_activity_demo"
android:screenOrientation="fullSensor"></activity>

<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
</application>

</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import android.content.Context
import androidx.preference.PreferenceManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.snowplow.Snowplow.createTracker
import com.snowplowanalytics.snowplow.configuration.*
import com.snowplowanalytics.snowplow.controller.TrackerController
Expand All @@ -32,6 +33,7 @@ class ApplicationInstallEventTest {
@Before
fun setUp() {
cleanSharedPreferences()
Executor.shutdown()
}

// Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class PlatformContextTest {
fun addsAllMockedInfo() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 0, deviceInfoMonitor, context = context)
Thread.sleep(100) // sleep in order to fetch the app set properties
val sdj = platformContext.getMobileContext(false)
val sdjMap = sdj!!.map
val sdjData = sdjMap["data"] as Map<*, *>?
Expand Down Expand Up @@ -79,6 +78,7 @@ class PlatformContextTest {
fun updatesMobileInfo() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 0, deviceInfoMonitor, context = context)
platformContext.getMobileContext(false)
Assert.assertEquals(
1,
deviceInfoMonitor.getMethodAccessCount("getSystemAvailableMemory").toLong()
Expand All @@ -98,10 +98,25 @@ class PlatformContextTest {
)
}

@Test
fun doesntFetchPropertiesIfNotRequested() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
PlatformContext(1000, 0, deviceInfoMonitor, context = context)
Assert.assertEquals(
0,
deviceInfoMonitor.getMethodAccessCount("getSystemAvailableMemory").toLong()
)
Assert.assertEquals(
0,
deviceInfoMonitor.getMethodAccessCount("getBatteryStateAndLevel").toLong()
)
}

@Test
fun doesntUpdateMobileInfoWithinUpdateWindow() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(1000, 0, deviceInfoMonitor, context = context)
platformContext.getMobileContext(false)
Assert.assertEquals(
1,
deviceInfoMonitor.getMethodAccessCount("getSystemAvailableMemory").toLong()
Expand All @@ -125,6 +140,7 @@ class PlatformContextTest {
fun updatesNetworkInfo() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 0, deviceInfoMonitor, context = context)
platformContext.getMobileContext(false)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getNetworkType").toLong())
Assert.assertEquals(
1,
Expand All @@ -142,6 +158,7 @@ class PlatformContextTest {
fun doesntUpdateNetworkInfoWithinUpdateWindow() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 1000, deviceInfoMonitor, context = context)
platformContext.getMobileContext(false)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getNetworkType").toLong())
Assert.assertEquals(
1,
Expand All @@ -159,6 +176,7 @@ class PlatformContextTest {
fun doesntUpdateNonEphemeralInfo() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 0, deviceInfoMonitor, context = context)
platformContext.getMobileContext(false)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getOsType").toLong())
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getTotalStorage").toLong())
platformContext.getMobileContext(false)
Expand All @@ -170,22 +188,10 @@ class PlatformContextTest {
fun doesntUpdateIdfaIfNotNull() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
val platformContext = PlatformContext(0, 1, deviceInfoMonitor, context = context)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
platformContext.getMobileContext(false)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
}

@Test
fun updatesIdfaIfEmptyOrNull() {
val deviceInfoMonitor = MockDeviceInfoMonitor()
deviceInfoMonitor.customIdfa = ""
val platformContext = PlatformContext(0, 1, deviceInfoMonitor, context = context)
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
deviceInfoMonitor.customIdfa = null
platformContext.getMobileContext(false)
Assert.assertEquals(2, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
platformContext.getMobileContext(false)
Assert.assertEquals(3, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
Assert.assertEquals(1, deviceInfoMonitor.getMethodAccessCount("getAndroidIdfa").toLong())
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package com.snowplowanalytics.core.tracker
import android.content.Context
import com.snowplowanalytics.core.constants.Parameters
import com.snowplowanalytics.core.constants.TrackerConstants
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.core.utils.DeviceInfoMonitor
import com.snowplowanalytics.core.utils.Util.addToMap
import com.snowplowanalytics.core.utils.Util.mapHasKeys
Expand Down Expand Up @@ -43,15 +42,12 @@ class PlatformContext(
private val context: Context,
) {
private val pairs: MutableMap<String, Any> = HashMap()
private var initializedPlatformDict = false
private var lastUpdatedEphemeralPlatformDict: Long = 0
private var lastUpdatedEphemeralNetworkDict: Long = 0

init {
setPlatformDict()
}

fun getMobileContext(userAnonymisation: Boolean): SelfDescribingJson? {
updateEphemeralDictsIfNecessary()
update()

// If does not contain the required properties, return null
if (!mapHasKeys(
Expand All @@ -76,7 +72,11 @@ class PlatformContext(

// --- PRIVATE
@Synchronized
private fun updateEphemeralDictsIfNecessary() {
private fun update() {
if (!initializedPlatformDict) {
setPlatformDict()
}

val now = System.currentTimeMillis()
if (now - lastUpdatedEphemeralPlatformDict >= platformDictUpdateFrequency) {
setEphemeralPlatformDict()
Expand Down Expand Up @@ -122,26 +122,25 @@ class PlatformContext(
if (shouldTrack(PlatformContextProperty.LANGUAGE)) {
addToMap(Parameters.MOBILE_LANGUAGE, (fromRetrieverOr(retriever.language) { deviceInfoMonitor.language })?.take(8), pairs)
}
// IDFA
if (shouldTrack(PlatformContextProperty.ANDROID_IDFA)) {
addToMap(
Parameters.ANDROID_IDFA,
fromRetrieverOr(retriever.androidIdfa) {
deviceInfoMonitor.getAndroidIdfa(context)
},
pairs
)
}

setEphemeralPlatformDict()
setEphemeralNetworkDict()
setAppSetId()

initializedPlatformDict = true
}

private fun setEphemeralPlatformDict() {
lastUpdatedEphemeralPlatformDict = System.currentTimeMillis()

// IDFA
if (shouldTrack(PlatformContextProperty.ANDROID_IDFA)) {
val currentIdfa = pairs[Parameters.ANDROID_IDFA]
if (currentIdfa == null || currentIdfa.toString().isEmpty()) {
addToMap(
Parameters.ANDROID_IDFA,
fromRetrieverOr(retriever.androidIdfa) { deviceInfoMonitor.getAndroidIdfa(context) },
pairs
)
}
}
// Battery
val trackBatState = shouldTrack(PlatformContextProperty.BATTERY_STATE)
val trackBatLevel = shouldTrack(PlatformContextProperty.BATTERY_LEVEL)
Expand Down Expand Up @@ -194,48 +193,25 @@ class PlatformContext(

/**
* Sets the app set information.
* The info has to be read on a background thread which often means that the first few
* tracked events will miss the info. To prevent that happening on the second start-up
* of the app, the info is saved in general prefs and read from there.
*/
private fun setAppSetId() {
val trackId = shouldTrack(PlatformContextProperty.APP_SET_ID)
val trackScope = shouldTrack(PlatformContextProperty.APP_SET_ID_SCOPE)
if (!trackId && !trackScope) { return }

val generalPref = context.getSharedPreferences(
TrackerConstants.SNOWPLOW_GENERAL_VARS,
Context.MODE_PRIVATE
)
val appSetId = fromRetrieverOr(retriever.appSetId) { generalPref.getString(Parameters.APP_SET_ID, null) }
val appSetIdScope = fromRetrieverOr(retriever.appSetIdScope) { generalPref.getString(Parameters.APP_SET_ID_SCOPE, null) }

if (appSetId != null && appSetIdScope != null) {
if (trackId) { addToMap(Parameters.APP_SET_ID, appSetId, pairs) }
if (trackScope) { addToMap(Parameters.APP_SET_ID_SCOPE, appSetIdScope, pairs) }
if (retriever.appSetId != null && retriever.appSetIdScope != null) {
if (trackId) { addToMap(Parameters.APP_SET_ID, retriever.appSetId?.invoke(), pairs) }
if (trackScope) { addToMap(Parameters.APP_SET_ID_SCOPE, retriever.appSetIdScope?.invoke(), pairs) }
} else {
Executor.execute(TAG) {
val preferences = generalPref.edit()
var edited = false

val appSetIdAndScope = deviceInfoMonitor.getAppSetIdAndScope(context)
val id = fromRetrieverOr(retriever.appSetId) {
val id = appSetIdAndScope?.first
preferences.putString(Parameters.APP_SET_ID, id)
edited = true
id
}
val scope = fromRetrieverOr(retriever.appSetIdScope) {
val scope = appSetIdAndScope?.second
preferences.putString(Parameters.APP_SET_ID_SCOPE, scope)
edited = true
scope
}

if (trackId) { addToMap(Parameters.APP_SET_ID, id, pairs) }
if (trackScope) { addToMap(Parameters.APP_SET_ID_SCOPE, scope, pairs) }

if (edited) { preferences.apply() }
val appSetIdAndScope = deviceInfoMonitor.getAppSetIdAndScope(context)

if (trackId) {
val id = fromRetrieverOr(retriever.appSetId) { appSetIdAndScope?.first }
addToMap(Parameters.APP_SET_ID, id, pairs)
}
if (trackScope) {
val scope = fromRetrieverOr(retriever.appSetIdScope) { appSetIdAndScope?.second }
addToMap(Parameters.APP_SET_ID_SCOPE, scope, pairs)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ open class DeviceInfoMonitor {

/**
* The function that actually fetches the Advertising ID.
* - If called from the UI Thread will throw an Exception
* Can't be called on the main UI thread.
*
* @param context the android context
* @return an empty string if limited tracking is on otherwise the advertising id or null
*/
open fun getAndroidIdfa(context: Context): String? {
if (Looper.myLooper() == Looper.getMainLooper()) { return null }

return try {
val advertisingInfoObject = invokeStaticMethod(
"com.google.android.gms.ads.identifier.AdvertisingIdClient",
Expand Down

0 comments on commit c1be49c

Please sign in to comment.