Skip to content

Commit

Permalink
Merge branch 'release/6.0.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
mscwilson committed Feb 14, 2024
2 parents 18cdf59 + e324998 commit bc58421
Show file tree
Hide file tree
Showing 17 changed files with 205 additions and 114 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
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)
Add percent progress to event (#662)

Version 6.0.0 (2024-02-01)
--------------------------
Enable lifecycle autotracking by default (#651)
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.0.0
6.0.1
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.0'
version = '6.0.1'
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.0
VERSION_NAME=6.0.1

POM_NAME=snowplow-android-tracker
POM_PACKAGING=aar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import android.view.View
import android.widget.MediaController
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.event.Event
import com.snowplowanalytics.snowplow.media.configuration.MediaTrackingConfiguration
import com.snowplowanalytics.snowplow.media.controller.MediaTracking
import com.snowplowanalytics.snowplow.media.entity.MediaPlayerEntity
import com.snowplowanalytics.snowplow.media.event.*
Expand Down Expand Up @@ -130,9 +131,14 @@ class VideoViewController(activity: Activity, uri: Uri) {
reset()
loaded = true

mediaTracking = Snowplow.defaultTracker?.media?.startMediaTracking(
val configuration = MediaTrackingConfiguration(
id = UUID.randomUUID().toString(),
player = player
player = player,
boundaries = listOf(10, 25, 50, 75),
)

mediaTracking = Snowplow.defaultTracker?.media?.startMediaTracking(
configuration
)

updateThread = UpdateThread()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,17 +383,14 @@ class TrackerTest {
}
Companion.tracker = Tracker(emitter, namespace, "myAppId", context = context, builder = trackerBuilder)
val screenState = Companion.tracker!!.getScreenState()
Assert.assertNotNull(screenState)
var screenStateMapWrapper: Map<String, Any?> = screenState!!.getCurrentScreen(true).map
var screenStateMap = screenStateMapWrapper[Parameters.DATA] as Map<String?, Any?>?
Assert.assertEquals("Unknown", screenStateMap!![Parameters.SCREEN_NAME])
Assert.assertNull(screenState)

// Send screenView
var screenView = ScreenView("screen1")
val screenId = screenView.dataPayload["id"] as String?
val eventId1 = Companion.tracker!!.track(screenView)
screenStateMapWrapper = Companion.tracker!!.getScreenState()!!.getCurrentScreen(true).map
screenStateMap = screenStateMapWrapper[Parameters.DATA] as Map<String?, Any?>?
val screenStateMapWrapper = Companion.tracker!!.getScreenState()!!.getCurrentScreen(true).map
val screenStateMap = screenStateMapWrapper[Parameters.DATA] as Map<*, *>?
Assert.assertEquals("screen1", screenStateMap!![Parameters.SCREEN_NAME])
Assert.assertEquals(screenId, screenStateMap[Parameters.SCREEN_ID])

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package com.snowplowanalytics.snowplow.media
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.core.media.MediaSchemata.eventSchema
import com.snowplowanalytics.core.media.MediaSchemata.playerSchema
import com.snowplowanalytics.core.media.MediaSchemata.sessionSchema
Expand Down Expand Up @@ -73,6 +74,7 @@ class TestMediaController {
tracker = null
removeAllTrackers()
trackedEvents.clear()
Executor.shutdown()
}

// --- MEDIA PLAYER EVENT TESTS
Expand Down Expand Up @@ -523,6 +525,29 @@ class TestMediaController {
assertEquals(3, trackedEvents.filter { it.schema == eventSchema("percent_progress") }.size)
}

@Test
fun progressEventShouldHavePercentValue() {
val configuration = MediaTrackingConfiguration(
id = "media1",
player = MediaPlayerEntity(duration = 100.0),
boundaries = listOf(50),
)
val media = tracker?.media?.startMediaTracking(configuration = configuration)

media?.track(MediaPlayEvent())
for (i in 1 until 60) {
media?.update(player = MediaPlayerEntity(currentTime = i.toDouble()))
}

Thread.sleep(100)

assertEquals(2, trackedEvents.size)

val progressEvents = trackedEvents.filter { it.schema == eventSchema("percent_progress") }
assertEquals(1, progressEvents.size)
assertEquals(50, progressEvents[0].payload["percentProgress"])
}

@Test
fun doesntSendProgressEventsIfPaused() {
val configuration = MediaTrackingConfiguration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@ import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.constants.TrackerConstants
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.core.utils.NotificationCenter
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.Snowplow.removeAllTrackers
import com.snowplowanalytics.snowplow.configuration.Configuration
import com.snowplowanalytics.snowplow.configuration.NetworkConfiguration
import com.snowplowanalytics.snowplow.configuration.PluginConfiguration
import com.snowplowanalytics.snowplow.controller.TrackerController
import com.snowplowanalytics.snowplow.event.ScreenView
import com.snowplowanalytics.snowplow.event.Structured
import com.snowplowanalytics.snowplow.network.HttpMethod
import com.snowplowanalytics.snowplow.payload.SelfDescribingJson
import com.snowplowanalytics.snowplow.util.EventSink
import org.junit.After
import org.junit.Assert
import org.junit.Test
Expand All @@ -39,21 +38,14 @@ class ScreenViewAutotrackingTest {
@After
fun tearDown() {
removeAllTrackers()
Executor.shutdown()
}

// --- TESTS
@Test
fun doesntTrackTheSameScreenViewMultipleTimes() {
var numberOfScreenViews = 0

val countPlugin = PluginConfiguration("test")
countPlugin.afterTrack {
if (it.schema == TrackerConstants.SCHEMA_SCREEN_VIEW) {
numberOfScreenViews += 1
}
}

createTracker(listOf(countPlugin))
val eventSink = EventSink()
createTracker(listOf(eventSink))
Thread.sleep(200)

NotificationCenter.postNotification("SnowplowScreenView", mapOf(
Expand All @@ -69,8 +61,9 @@ class ScreenViewAutotrackingTest {
NotificationCenter.postNotification("SnowplowScreenView", mapOf(
"event" to ScreenView(name = "Screen2").activityClassName("Screen2")
))
Thread.sleep(200)
Thread.sleep(500)

val numberOfScreenViews = eventSink.trackedEvents.filter { it.schema == TrackerConstants.SCHEMA_SCREEN_VIEW }.size
Assert.assertEquals(2, numberOfScreenViews)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright (c) 2015-present Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
package com.snowplowanalytics.snowplow.tracker

import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.constants.TrackerConstants
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.Snowplow.removeAllTrackers
import com.snowplowanalytics.snowplow.configuration.Configuration
import com.snowplowanalytics.snowplow.configuration.NetworkConfiguration
import com.snowplowanalytics.snowplow.controller.TrackerController
import com.snowplowanalytics.snowplow.event.*
import com.snowplowanalytics.snowplow.network.HttpMethod
import com.snowplowanalytics.snowplow.util.EventSink
import org.junit.After
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.util.*

@RunWith(AndroidJUnit4::class)
class ScreenStateMachineTest {

@Before
fun setUp() {
}

@After
fun tearDown() {
removeAllTrackers()
Executor.shutdown()
}

// --- TESTS

@Test
fun tracksEventsWithTheCorrectScreenEntityInfo() {
val eventSink = EventSink()
val tracker = createTracker(listOf(eventSink))

tracker.track(Timing(category = "c1", variable = "v1", timing = 1))
tracker.track(ScreenView(name = "Screen 1"))
tracker.track(Timing(category = "c2", variable = "v2", timing = 2))
tracker.track(ScreenView(name = "Screen 2"))
tracker.track(Timing(category = "c3", variable = "v3", timing = 3))
tracker.track(ScreenView(name = "Screen 3"))
tracker.track(Timing(category = "c4", variable = "v4", timing = 4))

Thread.sleep(200)

val events = eventSink.trackedEvents

val timingEvents = events.filter { it.schema == TrackerConstants.SCHEMA_USER_TIMINGS }
.sortedBy { it.payload["timing"] as Int }
Assert.assertEquals(4, timingEvents.size)

val screen0 = getScreenEntityData(timingEvents[0])
Assert.assertNull(screen0)

val screen1 = getScreenEntityData(timingEvents[1])
Assert.assertEquals("Screen 1", screen1?.get("name"))

val screen2 = getScreenEntityData(timingEvents[2])
Assert.assertEquals("Screen 2", screen2?.get("name"))

val screen3 = getScreenEntityData(timingEvents[3])
Assert.assertEquals("Screen 3", screen3?.get("name"))
}

// --- PRIVATE
private val context: Context
get() = InstrumentationRegistry.getInstrumentation().targetContext

private fun getScreenEntityData(event: InspectableEvent): Map<*, *>? {
val entity = event.entities.find { it.map["schema"] == TrackerConstants.SCHEMA_SCREEN }
return entity?.map?.get("data") as? Map<*, *>
}

private fun createTracker(configurations: List<Configuration>): TrackerController {
val networkConfig = NetworkConfiguration(MockNetworkConnection(HttpMethod.POST, 200))
return Snowplow.createTracker(
context,
namespace = "ns" + Math.random().toString(),
network = networkConfig,
configurations = configurations.toTypedArray()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.constants.TrackerConstants
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.core.screenviews.ScreenSummaryState
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.Snowplow.removeAllTrackers
import com.snowplowanalytics.snowplow.configuration.Configuration
import com.snowplowanalytics.snowplow.configuration.NetworkConfiguration
import com.snowplowanalytics.snowplow.configuration.PluginConfiguration
import com.snowplowanalytics.snowplow.controller.TrackerController
import com.snowplowanalytics.snowplow.event.*
import com.snowplowanalytics.snowplow.network.HttpMethod
import com.snowplowanalytics.snowplow.payload.SelfDescribingJson
import com.snowplowanalytics.snowplow.util.EventSink
import com.snowplowanalytics.snowplow.util.TimeTraveler
import org.junit.After
Expand All @@ -50,6 +49,7 @@ class ScreenSummaryStateMachineTest {
@After
fun tearDown() {
removeAllTrackers()
Executor.shutdown()
}

// --- TESTS
Expand Down Expand Up @@ -94,9 +94,14 @@ class ScreenSummaryStateMachineTest {
val events = eventSink.trackedEvents
Assert.assertEquals(3, events.size)

val screenSummary = getScreenSummary(events.find { it.schema == TrackerConstants.SCHEMA_SCREEN_END })
val screenEnd = events.find { it.schema == TrackerConstants.SCHEMA_SCREEN_END }
val screenSummary = getScreenSummary(screenEnd)
Assert.assertEquals(10.0, screenSummary?.get("foreground_sec"))
Assert.assertEquals(0.0, screenSummary?.get("background_sec"))

// should have the screen name of the first screen view
val screenEndScreen = screenEnd?.entities?.find { it.map["schema"] == TrackerConstants.SCHEMA_SCREEN }
Assert.assertEquals("Screen 1", (screenEndScreen?.map?.get("data") as? Map<*, *>)?.get("name"))
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package com.snowplowanalytics.snowplow.tracker
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.Snowplow.removeAllTrackers
import com.snowplowanalytics.snowplow.configuration.*
Expand All @@ -36,6 +37,7 @@ class FocalMeterConfigurationTest {
@After
fun tearDown() {
removeAllTrackers()
Executor.shutdown()
}

// --- TESTS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package com.snowplowanalytics.snowplow.tracker
import android.content.Context
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.snowplowanalytics.core.emitter.Executor
import com.snowplowanalytics.snowplow.Snowplow
import com.snowplowanalytics.snowplow.Snowplow.removeAllTrackers
import com.snowplowanalytics.snowplow.configuration.Configuration
Expand All @@ -38,6 +39,7 @@ class PluginsTest {
@After
fun tearDown() {
removeAllTrackers()
Executor.shutdown()
}

// --- TESTS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class MediaTrackingImpl (
// track events
event?.let { addEntitiesAndTrack(it) }
if (shouldSendPercentProgressEvent()) {
addEntitiesAndTrack(MediaPercentProgressEvent())
addEntitiesAndTrack(MediaPercentProgressEvent(this.player.percentProgress))
}

// update state for events after this one
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import com.snowplowanalytics.snowplow.event.AbstractSelfDescribing
/**
* Media player event fired when a percentage boundary set in the `boundaries` list in `MediaTrackingConfiguration` is reached.
*/
class MediaPercentProgressEvent : AbstractSelfDescribing() {
class MediaPercentProgressEvent(val percentProgress: Int?) : AbstractSelfDescribing() {
override val schema: String
get() = MediaSchemata.eventSchema("percent_progress")

override val dataPayload: Map<String, Any?>
get() = emptyMap()
get() = mapOf(
"percentProgress" to percentProgress,
)
}
Loading

0 comments on commit bc58421

Please sign in to comment.