From a107d2b91b8f8ec521c592bb2721e6d6d362fa30 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 18 Jul 2025 16:06:24 +0200 Subject: [PATCH 01/40] boilerplate and apis --- connectors/analytics/gemius/.gitignore | 1 + connectors/analytics/gemius/README.md | 0 connectors/analytics/gemius/build.gradle | 43 +++++++++++++++++++ .../analytics/gemius/consumer-rules.pro | 0 .../analytics/gemius/proguard-rules.pro | 21 +++++++++ .../gemius/src/main/AndroidManifest.xml | 4 ++ .../analytics/gemius/GemiusAdapter.kt | 30 +++++++++++++ .../analytics/gemius/GemiusConfiguration.kt | 10 +++++ .../analytics/gemius/GemiusConnector.kt | 21 +++++++++ 9 files changed, 130 insertions(+) create mode 100644 connectors/analytics/gemius/.gitignore create mode 100644 connectors/analytics/gemius/README.md create mode 100644 connectors/analytics/gemius/build.gradle create mode 100644 connectors/analytics/gemius/consumer-rules.pro create mode 100644 connectors/analytics/gemius/proguard-rules.pro create mode 100644 connectors/analytics/gemius/src/main/AndroidManifest.xml create mode 100644 connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt create mode 100644 connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConfiguration.kt create mode 100644 connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt diff --git a/connectors/analytics/gemius/.gitignore b/connectors/analytics/gemius/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/connectors/analytics/gemius/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/connectors/analytics/gemius/README.md b/connectors/analytics/gemius/README.md new file mode 100644 index 00000000..e69de29b diff --git a/connectors/analytics/gemius/build.gradle b/connectors/analytics/gemius/build.gradle new file mode 100644 index 00000000..12c0b13c --- /dev/null +++ b/connectors/analytics/gemius/build.gradle @@ -0,0 +1,43 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin.android) +} + +android { + namespace 'com.theoplayer.android.connector.analytics.gemius' + compileSdk 35 + + defaultConfig { + minSdk 21 + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles "consumer-rules.pro" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = '11' + } +} + +dependencies { + + implementation libs.androidx.core.ktx + implementation libs.androidx.appcompat + implementation libs.material + compileOnly fileTree(dir: './libs/GemiusSDK_2.0.8.aar', include: ['*.aar', '*.jar'], exclude: []) + compileOnly "com.theoplayer.theoplayer-sdk-android:core:$sdkVersion" + compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:$sdkVersion" + testImplementation libs.junit + androidTestImplementation libs.androidx.test.ext.junit + androidTestImplementation libs.androidx.test.espresso.core +} \ No newline at end of file diff --git a/connectors/analytics/gemius/consumer-rules.pro b/connectors/analytics/gemius/consumer-rules.pro new file mode 100644 index 00000000..e69de29b diff --git a/connectors/analytics/gemius/proguard-rules.pro b/connectors/analytics/gemius/proguard-rules.pro new file mode 100644 index 00000000..481bb434 --- /dev/null +++ b/connectors/analytics/gemius/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/connectors/analytics/gemius/src/main/AndroidManifest.xml b/connectors/analytics/gemius/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a5918e68 --- /dev/null +++ b/connectors/analytics/gemius/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt new file mode 100644 index 00000000..52c72c8c --- /dev/null +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -0,0 +1,30 @@ +package com.theoplayer.android.connector.analytics.gemius + +import com.theoplayer.android.api.THEOplayerView +import com.gemius.sdk.stream.Player +import com.gemius.sdk.stream.PlayerData +import com.gemius.sdk.stream.ProgramData + +val PLAYER_ID = "THEOplayer" + +class GemiusAdapter( + configuration: GemiusConfiguration, + playerView: THEOplayerView, + adProcessor: AdProcessor? +) { + private val gemiusPlayer: Player? + private var programId: String? = null + private var programData: ProgramData? = null + + init { + val playerData = PlayerData() + gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) + + } + + fun update(programId: String, programData: ProgramData) { + this.programId = programId + this.programData = programData + } + +} \ No newline at end of file diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConfiguration.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConfiguration.kt new file mode 100644 index 00000000..5d0c4b10 --- /dev/null +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConfiguration.kt @@ -0,0 +1,10 @@ +package com.theoplayer.android.connector.analytics.gemius + +data class GemiusConfiguration ( + val applicationName: String, + val applicationVersion: String, + val hitCollectorHost: String, + val gemiusId: String, + val debug: Boolean, + val adProcessor: AdProcessor? +) \ No newline at end of file diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt new file mode 100644 index 00000000..fc68ce1a --- /dev/null +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt @@ -0,0 +1,21 @@ +package com.theoplayer.android.connector.analytics.gemius + +import com.gemius.sdk.stream.AdData +import com.gemius.sdk.stream.ProgramData +import com.theoplayer.android.api.THEOplayerView +import com.theoplayer.android.api.ads.Ad + +interface AdProcessor { + fun apply(input: Ad): AdData +} + +class GemiusConnector( + configuration: GemiusConfiguration, + playerView: THEOplayerView, +) { + private val gemiusAdapter = GemiusAdapter(configuration,playerView, configuration.adProcessor) + + fun update(programId: String, programData: ProgramData) { + gemiusAdapter.update(programId, programData) + } +} \ No newline at end of file From 6ce4048dd2ced68d8c72bd3776b091b4ee825b63 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 18 Jul 2025 16:18:20 +0200 Subject: [PATCH 02/40] config --- gradle/libs.versions.toml | 2 ++ settings.gradle | 2 ++ 2 files changed, 4 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 99b80574..407011ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,6 +24,7 @@ conviva = "4.0.43" nielsen = "9.2.0.0" comscore = "6.10.0" yospace = "3.6.7" +material = "1.12.0" [libraries] androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidxAppCompat" } @@ -52,6 +53,7 @@ conviva = { group = "com.conviva.sdk", name = "conviva-core-sdk", version.ref = nielsen = { group = "com.nielsenappsdk.global", name = "ad", version.ref = "nielsen" } comscore = { group = "com.comscore", name = "android-analytics", version.ref = "comscore" } yospace = { group = "com.yospace", name = "admanagement-sdk", version.ref = "yospace" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } [plugins] android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } diff --git a/settings.gradle b/settings.gradle index dcdf50c3..7aafcda8 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,8 @@ include ':app' include ':connectors:analytics:comscore' include ':connectors:analytics:conviva' include ':connectors:analytics:nielsen' +include ':connectors:analytics:gemius' include ':connectors:mediasession' include ':connectors:yospace' include ':connectors:uplynk' +include ':connectors:analytics:gemius' From 2d16f3982d5da2961976585d0529132983c8591f Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 18 Jul 2025 17:43:37 +0200 Subject: [PATCH 03/40] provide context --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 3 +++ .../android/connector/analytics/gemius/GemiusConnector.kt | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 52c72c8c..94428a35 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -1,5 +1,6 @@ package com.theoplayer.android.connector.analytics.gemius +import android.content.Context import com.theoplayer.android.api.THEOplayerView import com.gemius.sdk.stream.Player import com.gemius.sdk.stream.PlayerData @@ -8,6 +9,7 @@ import com.gemius.sdk.stream.ProgramData val PLAYER_ID = "THEOplayer" class GemiusAdapter( + context: Context, configuration: GemiusConfiguration, playerView: THEOplayerView, adProcessor: AdProcessor? @@ -19,6 +21,7 @@ class GemiusAdapter( init { val playerData = PlayerData() gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) + gemiusPlayer.setContext(context) } diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt index fc68ce1a..0d907aa6 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt @@ -1,5 +1,6 @@ package com.theoplayer.android.connector.analytics.gemius +import android.content.Context import com.gemius.sdk.stream.AdData import com.gemius.sdk.stream.ProgramData import com.theoplayer.android.api.THEOplayerView @@ -10,10 +11,11 @@ interface AdProcessor { } class GemiusConnector( + context: Context, configuration: GemiusConfiguration, playerView: THEOplayerView, ) { - private val gemiusAdapter = GemiusAdapter(configuration,playerView, configuration.adProcessor) + private val gemiusAdapter = GemiusAdapter(context,configuration,playerView, configuration.adProcessor) fun update(programId: String, programData: ProgramData) { gemiusAdapter.update(programId, programData) From cbe8025fa1b1a47a403b1333226c27d3203606cf Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 18 Jul 2025 17:43:56 +0200 Subject: [PATCH 04/40] include PlayerData --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 94428a35..90f707d1 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -20,6 +20,8 @@ class GemiusAdapter( init { val playerData = PlayerData() + playerData.resolution = "${playerView.width}x${playerView.height}" + playerData.volume = if (playerView.player.isMuted) -1 else (playerView.player.volume * 100).toInt() gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) gemiusPlayer.setContext(context) From e01474711c2fecac9e61d731f2d6f89ea765ebc3 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 18 Jul 2025 22:36:21 +0200 Subject: [PATCH 05/40] event listeners --- .../analytics/gemius/GemiusAdapter.kt | 156 +++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 90f707d1..2d3a1580 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -1,23 +1,69 @@ package com.theoplayer.android.connector.analytics.gemius import android.content.Context +import android.util.Log import com.theoplayer.android.api.THEOplayerView import com.gemius.sdk.stream.Player import com.gemius.sdk.stream.PlayerData import com.gemius.sdk.stream.ProgramData +import com.theoplayer.android.api.ads.Ad +import com.theoplayer.android.api.event.EventListener +import com.theoplayer.android.api.event.ads.AdBeginEvent +import com.theoplayer.android.api.event.ads.AdBreakBeginEvent +import com.theoplayer.android.api.event.ads.AdBreakEndEvent +import com.theoplayer.android.api.event.ads.AdEndEvent +import com.theoplayer.android.api.event.ads.AdSkipEvent +import com.theoplayer.android.api.event.player.EndedEvent +import com.theoplayer.android.api.event.player.ErrorEvent +import com.theoplayer.android.api.event.player.PauseEvent +import com.theoplayer.android.api.event.player.PlayEvent +import com.theoplayer.android.api.event.player.PlayingEvent +import com.theoplayer.android.api.event.player.SeekingEvent +import com.theoplayer.android.api.event.player.SourceChangeEvent +import com.theoplayer.android.api.event.player.VolumeChangeEvent +import com.theoplayer.android.api.event.player.WaitingEvent +import com.theoplayer.android.api.event.track.mediatrack.audio.QualityChangedEvent +import com.theoplayer.android.api.event.track.mediatrack.video.list.AddTrackEvent +import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackEvent val PLAYER_ID = "THEOplayer" +val TAG = "GemiusConnector" class GemiusAdapter( context: Context, - configuration: GemiusConfiguration, - playerView: THEOplayerView, - adProcessor: AdProcessor? + private val configuration: GemiusConfiguration, + private val playerView: THEOplayerView, + private val adProcessor: AdProcessor? ) { private val gemiusPlayer: Player? + private var programId: String? = null private var programData: ProgramData? = null + private var partCount: Int = 1 + private var adCount: Int = 1 + private var currentAd: Ad? = null + + private val onSourceChange: EventListener + private val onFirstPlaying: EventListener + private val onPlay: EventListener + private val onPause: EventListener + private val onWaiting: EventListener + private val onSeeking: EventListener + private val onError: EventListener + private val onEnded: EventListener + private val onVolumeChange: EventListener + + private val onAddVideoTrack: EventListener + private val onRemoveVideoTrack: EventListener + private val onVideoQualityChanged: EventListener> + + private val onAdBreakBeginListener: EventListener + private val onAdBeginListener: EventListener + private val onAdEndListener: EventListener + private val onAdSkipListener: EventListener + private val onAdBreakEndedListener: EventListener + init { val playerData = PlayerData() playerData.resolution = "${playerView.width}x${playerView.height}" @@ -25,6 +71,24 @@ class GemiusAdapter( gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) gemiusPlayer.setContext(context) + onSourceChange = EventListener { event -> handleSourceChange(event) } + onFirstPlaying = EventListener { event -> handleFirstPlaying(event) } + onPlay = EventListener { event -> handlePlay(event) } + onPause = EventListener { event -> handlePause(event) } + onWaiting = EventListener { event -> handleWaiting(event) } + onSeeking = EventListener { event -> handleSeeking(event) } + onError = EventListener { event -> handleError(event) } + onEnded = EventListener { event -> handleEnded(event) } + onVolumeChange = EventListener { event -> handleVolumeChange(event) } + onAddVideoTrack = EventListener { event -> handleAddVideoTrack(event) } + onRemoveVideoTrack = EventListener { event -> handleRemoveVideoTrack(event) } + onVideoQualityChanged = EventListener { event -> handleVideoQualityChanged(event) } + onAdBreakBeginListener = EventListener { event -> handleAdBreakBegin(event) } + onAdBeginListener = EventListener { event -> handleAdBegin(event) } + onAdEndListener = EventListener { event -> handleAdEnd(event) } + onAdSkipListener = EventListener { event -> handleAdSkip(event) } + onAdBreakEndedListener = EventListener { event -> handleAdBreakEnded(event) } + } fun update(programId: String, programData: ProgramData) { @@ -32,4 +96,90 @@ class GemiusAdapter( this.programData = programData } + private fun handleSourceChange(event: SourceChangeEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleFirstPlaying(event: PlayingEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handlePlay(event: PlayEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handlePause(event: PauseEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleWaiting(event: WaitingEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleSeeking(event: SeekingEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleError(event: ErrorEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleEnded(event: EndedEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleVolumeChange(event: VolumeChangeEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAddVideoTrack(event: AddTrackEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleRemoveVideoTrack(event: RemoveTrackEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleVideoQualityChanged(event: QualityChangedEvent<*,*>) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAdBreakBegin(event: AdBreakBeginEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAdBegin(event: AdBeginEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAdEnd(event: AdEndEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAdSkip(event: AdSkipEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + private fun handleAdBreakEnded(event: AdBreakEndEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}") + } + } + } \ No newline at end of file From 975baae7e04816cd2c85c874a9bca86b3c44be1a Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 09:05:41 +0200 Subject: [PATCH 06/40] add listeners --- .../analytics/gemius/GemiusAdapter.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 2d3a1580..d703b773 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -13,10 +13,12 @@ import com.theoplayer.android.api.event.ads.AdBreakBeginEvent import com.theoplayer.android.api.event.ads.AdBreakEndEvent import com.theoplayer.android.api.event.ads.AdEndEvent import com.theoplayer.android.api.event.ads.AdSkipEvent +import com.theoplayer.android.api.event.ads.AdsEventTypes import com.theoplayer.android.api.event.player.EndedEvent import com.theoplayer.android.api.event.player.ErrorEvent import com.theoplayer.android.api.event.player.PauseEvent import com.theoplayer.android.api.event.player.PlayEvent +import com.theoplayer.android.api.event.player.PlayerEventTypes import com.theoplayer.android.api.event.player.PlayingEvent import com.theoplayer.android.api.event.player.SeekingEvent import com.theoplayer.android.api.event.player.SourceChangeEvent @@ -25,6 +27,8 @@ import com.theoplayer.android.api.event.player.WaitingEvent import com.theoplayer.android.api.event.track.mediatrack.audio.QualityChangedEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.AddTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackEvent +import com.theoplayer.android.api.event.track.mediatrack.video.list.VideoTrackListEventTypes +import com.theoplayer.android.api.event.track.tracklist.TrackListEvent val PLAYER_ID = "THEOplayer" val TAG = "GemiusConnector" @@ -89,6 +93,7 @@ class GemiusAdapter( onAdSkipListener = EventListener { event -> handleAdSkip(event) } onAdBreakEndedListener = EventListener { event -> handleAdBreakEnded(event) } + addEventListeners() } fun update(programId: String, programData: ProgramData) { @@ -96,6 +101,25 @@ class GemiusAdapter( this.programData = programData } + private fun addEventListeners() { + playerView.player.addEventListener(PlayerEventTypes.SOURCECHANGE, onSourceChange) + playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) + playerView.player.addEventListener(PlayerEventTypes.PLAY, onPlay) + playerView.player.addEventListener(PlayerEventTypes.PAUSE, onPause) + playerView.player.addEventListener(PlayerEventTypes.WAITING, onWaiting) + playerView.player.addEventListener(PlayerEventTypes.SEEKING, onSeeking) + playerView.player.addEventListener(PlayerEventTypes.ERROR, onError) + playerView.player.addEventListener(PlayerEventTypes.ENDED, onEnded) + playerView.player.addEventListener(PlayerEventTypes.VOLUMECHANGE, onVolumeChange) + playerView.player.videoTracks.addEventListener(VideoTrackListEventTypes.ADDTRACK, onAddVideoTrack) + playerView.player.videoTracks.addEventListener(VideoTrackListEventTypes.REMOVETRACK, onRemoveVideoTrack) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_BEGIN, onAdBreakBeginListener) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BEGIN, onAdBeginListener) + playerView.player.ads.addEventListener(AdsEventTypes.AD_END, onAdEndListener) + playerView.player.ads.addEventListener(AdsEventTypes.AD_SKIP, onAdSkipListener) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_END, onAdBreakEndedListener) + } + private fun handleSourceChange(event: SourceChangeEvent) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}") From c5ca64df5d29fcd0264c379471b0daa42cb2a29d Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 15:24:47 +0200 Subject: [PATCH 07/40] handle sourcechange --- .../connector/analytics/gemius/GemiusAdapter.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index d703b773..b91ae58d 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -122,8 +122,15 @@ class GemiusAdapter( private fun handleSourceChange(event: SourceChangeEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") - } + Log.d(TAG, "Player Event: ${event.type}: source = ${event.source.toString()}") + } + partCount = 1 + currentAd = null + val programId = this.programId ?: return + val programData = this.programData ?: return + gemiusPlayer?.newProgram(programId,programData) + playerView.player.removeEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) + playerView.player.addEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) } private fun handleFirstPlaying(event: PlayingEvent) { if (configuration.debug) { From fb3f9095bce72d01915d41b42be52ee176278190 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 15:30:13 +0200 Subject: [PATCH 08/40] use const --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index b91ae58d..cc3afbf9 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -30,8 +30,8 @@ import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackE import com.theoplayer.android.api.event.track.mediatrack.video.list.VideoTrackListEventTypes import com.theoplayer.android.api.event.track.tracklist.TrackListEvent -val PLAYER_ID = "THEOplayer" -val TAG = "GemiusConnector" +const val PLAYER_ID = "THEOplayer" +const val TAG = "GemiusConnector" class GemiusAdapter( context: Context, From 724cf5bd35b92d96ca03e47d7916c3fc3f57ffe9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:07:59 +0200 Subject: [PATCH 09/40] handle playing --- .../analytics/gemius/GemiusAdapter.kt | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index cc3afbf9..c51ed447 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -2,11 +2,15 @@ package com.theoplayer.android.connector.analytics.gemius import android.content.Context import android.util.Log +import com.gemius.sdk.stream.EventAdData +import com.gemius.sdk.stream.EventProgramData import com.theoplayer.android.api.THEOplayerView import com.gemius.sdk.stream.Player import com.gemius.sdk.stream.PlayerData import com.gemius.sdk.stream.ProgramData import com.theoplayer.android.api.ads.Ad +import com.theoplayer.android.api.ads.LinearAd +import com.theoplayer.android.api.ads.ima.GoogleImaAd import com.theoplayer.android.api.event.EventListener import com.theoplayer.android.api.event.ads.AdBeginEvent import com.theoplayer.android.api.event.ads.AdBreakBeginEvent @@ -71,7 +75,7 @@ class GemiusAdapter( init { val playerData = PlayerData() playerData.resolution = "${playerView.width}x${playerView.height}" - playerData.volume = if (playerView.player.isMuted) -1 else (playerView.player.volume * 100).toInt() + playerData.volume = computeVolume() gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) gemiusPlayer.setContext(context) @@ -101,6 +105,10 @@ class GemiusAdapter( this.programData = programData } + private fun computeVolume(): Int { + return if (playerView.player.isMuted) -1 else (playerView.player.volume * 100).toInt() + } + private fun addEventListeners() { playerView.player.addEventListener(PlayerEventTypes.SOURCECHANGE, onSourceChange) playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) @@ -134,8 +142,32 @@ class GemiusAdapter( } private fun handleFirstPlaying(event: PlayingEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") + } + val computedVolume = computeVolume() + val programId = programId ?: return + currentAd?.let { ad -> + val adId = ad.id + val adBreak = ad.adBreak ?: return + val offset = adBreak.timeOffset + val adEventData = EventAdData() + adEventData.volume = computedVolume + adEventData.breakSize = adBreak.ads.size + if (ad is LinearAd) adEventData.adDuration = ad.duration + adEventData.adPosition = adCount + gemiusPlayer?.adEvent(programId, adId, offset, Player.EventType.PLAY, adEventData) + } ?: run { + val player = playerView.player + val currentQuality = player.videoTracks.first { track -> track.isEnabled }.activeQuality + val programEventData = EventProgramData() + programEventData.volume = computedVolume + programEventData.programDuration = player.duration.toInt() + programEventData.partID = partCount + programEventData.autoPlay = player.isAutoplay + if (currentQuality!= null) programEventData.quality = "${currentQuality.width}x${currentQuality.height}" + gemiusPlayer?.programEvent(programId, player.currentTime.toInt(), Player.EventType.PLAY, ) } + } private fun handlePlay(event: PlayEvent) { if (configuration.debug) { From 87ca2d17b754ce47e46f676e6218e57d7f9ce6c9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:08:57 +0200 Subject: [PATCH 10/40] pass program event data --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index c51ed447..00cc13c1 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -165,9 +165,8 @@ class GemiusAdapter( programEventData.partID = partCount programEventData.autoPlay = player.isAutoplay if (currentQuality!= null) programEventData.quality = "${currentQuality.width}x${currentQuality.height}" - gemiusPlayer?.programEvent(programId, player.currentTime.toInt(), Player.EventType.PLAY, ) + gemiusPlayer?.programEvent(programId, player.currentTime.toInt(), Player.EventType.PLAY, programEventData) } - } private fun handlePlay(event: PlayEvent) { if (configuration.debug) { From d7cb0a45cc542b82672faa4ec671641665525081 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:09:57 +0200 Subject: [PATCH 11/40] move logic to play handler --- .../connector/analytics/gemius/GemiusAdapter.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 00cc13c1..fa3b505b 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -144,6 +144,12 @@ class GemiusAdapter( if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } + + } + private fun handlePlay(event: PlayEvent) { + if (configuration.debug) { + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") + } val computedVolume = computeVolume() val programId = programId ?: return currentAd?.let { ad -> @@ -168,11 +174,6 @@ class GemiusAdapter( gemiusPlayer?.programEvent(programId, player.currentTime.toInt(), Player.EventType.PLAY, programEventData) } } - private fun handlePlay(event: PlayEvent) { - if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") - } - } private fun handlePause(event: PauseEvent) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}") From fd347960e5c1365bc8f071bfdf63a61214f101aa Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:17:18 +0200 Subject: [PATCH 12/40] stick to playing event only --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index fa3b505b..a48045cf 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -81,7 +81,7 @@ class GemiusAdapter( onSourceChange = EventListener { event -> handleSourceChange(event) } onFirstPlaying = EventListener { event -> handleFirstPlaying(event) } - onPlay = EventListener { event -> handlePlay(event) } +// onPlay = EventListener { event -> handlePlay(event) } onPause = EventListener { event -> handlePause(event) } onWaiting = EventListener { event -> handleWaiting(event) } onSeeking = EventListener { event -> handleSeeking(event) } @@ -144,12 +144,6 @@ class GemiusAdapter( if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } - - } - private fun handlePlay(event: PlayEvent) { - if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") - } val computedVolume = computeVolume() val programId = programId ?: return currentAd?.let { ad -> From 73318b6b3d0ca7a6223cc06ddcf2a4d0af4eeb7b Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:28:01 +0200 Subject: [PATCH 13/40] comment play logic --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index a48045cf..34870aea 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -54,7 +54,7 @@ class GemiusAdapter( private val onSourceChange: EventListener private val onFirstPlaying: EventListener - private val onPlay: EventListener +// private val onPlay: EventListener private val onPause: EventListener private val onWaiting: EventListener private val onSeeking: EventListener @@ -112,7 +112,7 @@ class GemiusAdapter( private fun addEventListeners() { playerView.player.addEventListener(PlayerEventTypes.SOURCECHANGE, onSourceChange) playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) - playerView.player.addEventListener(PlayerEventTypes.PLAY, onPlay) +// playerView.player.addEventListener(PlayerEventTypes.PLAY, onPlay) playerView.player.addEventListener(PlayerEventTypes.PAUSE, onPause) playerView.player.addEventListener(PlayerEventTypes.WAITING, onWaiting) playerView.player.addEventListener(PlayerEventTypes.SEEKING, onSeeking) From 33c34d3914736053cccf312a46a405ced2f16eba Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:28:13 +0200 Subject: [PATCH 14/40] handle pause --- .../connector/analytics/gemius/GemiusAdapter.kt | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 34870aea..ecbd5600 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -170,9 +170,23 @@ class GemiusAdapter( } private fun handlePause(event: PauseEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } + reportBasicEvent(Player.EventType.PAUSE) } + + private fun reportBasicEvent(eventType: Player.EventType) { + val programId = programId ?: return + currentAd?.let { ad -> + val offset = ad.adBreak?.timeOffset ?: return + // docs mention null can be passed but interface prohibits + gemiusPlayer?.adEvent(programId,ad.id, offset, eventType, EventAdData()) + } ?: run { + // docs mention null can be passed but interface prohibits + gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), eventType, EventProgramData()) + } + } + private fun handleWaiting(event: WaitingEvent) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}") From e6411c3412caf0f0b6e01059825f8569fc11a9f2 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:28:58 +0200 Subject: [PATCH 15/40] handle waiting --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index ecbd5600..54c82804 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -189,8 +189,9 @@ class GemiusAdapter( private fun handleWaiting(event: WaitingEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } + reportBasicEvent(Player.EventType.BUFFER) } private fun handleSeeking(event: SeekingEvent) { if (configuration.debug) { From 6748afe4999c3714115ca9b28d6237ba687b17ba Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:29:34 +0200 Subject: [PATCH 16/40] move down --- .../analytics/gemius/GemiusAdapter.kt | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 54c82804..0f1ba5f3 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -174,19 +174,6 @@ class GemiusAdapter( } reportBasicEvent(Player.EventType.PAUSE) } - - private fun reportBasicEvent(eventType: Player.EventType) { - val programId = programId ?: return - currentAd?.let { ad -> - val offset = ad.adBreak?.timeOffset ?: return - // docs mention null can be passed but interface prohibits - gemiusPlayer?.adEvent(programId,ad.id, offset, eventType, EventAdData()) - } ?: run { - // docs mention null can be passed but interface prohibits - gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), eventType, EventProgramData()) - } - } - private fun handleWaiting(event: WaitingEvent) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") @@ -253,5 +240,15 @@ class GemiusAdapter( Log.d(TAG, "Player Event: ${event.type}") } } - + private fun reportBasicEvent(eventType: Player.EventType) { + val programId = programId ?: return + currentAd?.let { ad -> + val offset = ad.adBreak?.timeOffset ?: return + // docs mention null can be passed but interface prohibits + gemiusPlayer?.adEvent(programId,ad.id, offset, eventType, EventAdData()) + } ?: run { + // docs mention null can be passed but interface prohibits + gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), eventType, EventProgramData()) + } + } } \ No newline at end of file From 7426d13cdf431031c9363afb42849f0147fc0dc3 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:30:04 +0200 Subject: [PATCH 17/40] handle seeking --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 0f1ba5f3..0e1d3c94 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -182,8 +182,9 @@ class GemiusAdapter( } private fun handleSeeking(event: SeekingEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } + reportBasicEvent(Player.EventType.SEEK) } private fun handleError(event: ErrorEvent) { if (configuration.debug) { From fbbd0527f7ab6d887aebe7c6e7b335ddbcd46d64 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:32:37 +0200 Subject: [PATCH 18/40] handle ended and error --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 0e1d3c94..c383e261 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -188,13 +188,16 @@ class GemiusAdapter( } private fun handleError(event: ErrorEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + val errorObject = event.errorObject + Log.d(TAG, "Player Event: ${event.type}: error = ${errorObject.code}: ${errorObject.message}") } + reportBasicEvent(Player.EventType.COMPLETE) } private fun handleEnded(event: EndedEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } + reportBasicEvent(Player.EventType.COMPLETE) } private fun handleVolumeChange(event: VolumeChangeEvent) { if (configuration.debug) { From f9f355c9d1e85e36b7771f74166b0f6c74a1dbab Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 19 Jul 2025 16:44:33 +0200 Subject: [PATCH 19/40] handle volumechange --- .../connector/analytics/gemius/GemiusAdapter.kt | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index c383e261..a7bd0e8f 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -201,7 +201,19 @@ class GemiusAdapter( } private fun handleVolumeChange(event: VolumeChangeEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: volume = ${event.volume}") + } + val computedVolume = computeVolume() + val programId = programId ?: return + currentAd?.let { ad -> + val adBreak = ad.adBreak ?: return + val adEventData = EventAdData() + adEventData.volume = computedVolume + gemiusPlayer?.adEvent(programId, ad.id, adBreak.timeOffset, Player.EventType.CHANGE_VOL, adEventData) + } ?: run { + val programEventData = EventProgramData() + programEventData.volume = computedVolume + gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), Player.EventType.CHANGE_VOL, programEventData) } } private fun handleAddVideoTrack(event: AddTrackEvent) { From 892da47255d19e625b73e89cf71121ce9af84470 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sun, 20 Jul 2025 22:16:53 +0200 Subject: [PATCH 20/40] handle video quality changes --- .../analytics/gemius/GemiusAdapter.kt | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index a7bd0e8f..8fb14c00 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -11,6 +11,7 @@ import com.gemius.sdk.stream.ProgramData import com.theoplayer.android.api.ads.Ad import com.theoplayer.android.api.ads.LinearAd import com.theoplayer.android.api.ads.ima.GoogleImaAd +import com.theoplayer.android.api.event.Event import com.theoplayer.android.api.event.EventListener import com.theoplayer.android.api.event.ads.AdBeginEvent import com.theoplayer.android.api.event.ads.AdBreakBeginEvent @@ -29,10 +30,12 @@ import com.theoplayer.android.api.event.player.SourceChangeEvent import com.theoplayer.android.api.event.player.VolumeChangeEvent import com.theoplayer.android.api.event.player.WaitingEvent import com.theoplayer.android.api.event.track.mediatrack.audio.QualityChangedEvent +import com.theoplayer.android.api.event.track.mediatrack.video.VideoTrackEventTypes import com.theoplayer.android.api.event.track.mediatrack.video.list.AddTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.VideoTrackListEventTypes import com.theoplayer.android.api.event.track.tracklist.TrackListEvent +import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality const val PLAYER_ID = "THEOplayer" const val TAG = "GemiusConnector" @@ -218,18 +221,36 @@ class GemiusAdapter( } private fun handleAddVideoTrack(event: AddTrackEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event (Video Track): ${event.type}") } + val track = event.track + track.addEventListener(VideoTrackEventTypes.ACTIVEQUALITYCHANGEDEVENT, onVideoQualityChanged) } private fun handleRemoveVideoTrack(event: RemoveTrackEvent) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}") } + val track = event.track + track.removeEventListener(VideoTrackEventTypes.ACTIVEQUALITYCHANGEDEVENT, onVideoQualityChanged) } private fun handleVideoQualityChanged(event: QualityChangedEvent<*,*>) { if (configuration.debug) { Log.d(TAG, "Player Event: ${event.type}") } + val programId = programId ?: return + val activeQuality = (event.getQuality() as VideoQuality) + val height = activeQuality.height + val width = activeQuality.width + currentAd?.let { ad -> + val adBreak = ad.adBreak ?: return + val adEventData = EventAdData() + adEventData.quality = "${width}x${height}" + gemiusPlayer?.adEvent(programId,ad.id,adBreak.timeOffset,Player.EventType.CHANGE_QUAL,adEventData) + } ?: run { + val programEventData = EventProgramData() + programEventData.quality = "${width}x${height}" + gemiusPlayer?.programEvent(programId,playerView.player.currentTime.toInt(),Player.EventType.CHANGE_QUAL,programEventData) + } } private fun handleAdBreakBegin(event: AdBreakBeginEvent) { if (configuration.debug) { From 1a2589666fca08cb1fa67938330025749fc059f2 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:29:10 +0200 Subject: [PATCH 21/40] handle ad break begin --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 8fb14c00..6824c78a 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -254,8 +254,11 @@ class GemiusAdapter( } private fun handleAdBreakBegin(event: AdBreakBeginEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: offset = ${event.adBreak.timeOffset}") } + reportBasicEvent(Player.EventType.BREAK) + playerView.player.removeEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) + playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) } private fun handleAdBegin(event: AdBeginEvent) { if (configuration.debug) { From b76f31c88a868a82a6d25e69d3154224649bde81 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:49:58 +0200 Subject: [PATCH 22/40] handle ad begin --- .../analytics/gemius/GemiusAdapter.kt | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 6824c78a..08c5e927 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -2,6 +2,7 @@ package com.theoplayer.android.connector.analytics.gemius import android.content.Context import android.util.Log +import com.gemius.sdk.stream.AdData import com.gemius.sdk.stream.EventAdData import com.gemius.sdk.stream.EventProgramData import com.theoplayer.android.api.THEOplayerView @@ -261,9 +262,14 @@ class GemiusAdapter( playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) } private fun handleAdBegin(event: AdBeginEvent) { + val ad = event.ad + currentAd = ad + val adId = ad?.id ?: return if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: id = ${adId}") } + val adData = buildAdData(ad) + gemiusPlayer?.newAd(adId,adData) } private fun handleAdEnd(event: AdEndEvent) { if (configuration.debug) { @@ -291,4 +297,20 @@ class GemiusAdapter( gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), eventType, EventProgramData()) } } + + private fun buildAdData(ad: Ad): AdData { + val adData = AdData() + val linearAd = ad as? LinearAd ?: return adData + configuration.adProcessor?.let { adProcessor -> + return adProcessor.apply(ad) + } ?: run { + adData.name = linearAd.id + adData.adType = AdData.AdType.BREAK + adData.adFormat = 1 // 1 = VIDEO ; 2 = AUDIO + adData.duration = linearAd.duration + adData.quality = "${playerView.player.videoWidth}x${playerView.player.videoHeight}" + adData.resolution = "${playerView.width}x${playerView.height}" + return adData + } + } } \ No newline at end of file From 6ffca4a7330091d5e86ca411e1fad6a8eb3e6aa6 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:52:06 +0200 Subject: [PATCH 23/40] rename --- .../analytics/gemius/GemiusAdapter.kt | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 08c5e927..3183f56b 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -70,11 +70,11 @@ class GemiusAdapter( private val onRemoveVideoTrack: EventListener private val onVideoQualityChanged: EventListener> - private val onAdBreakBeginListener: EventListener - private val onAdBeginListener: EventListener - private val onAdEndListener: EventListener - private val onAdSkipListener: EventListener - private val onAdBreakEndedListener: EventListener + private val onAdBreakBegin: EventListener + private val onAdBegin: EventListener + private val onAdEnd: EventListener + private val onAdSkip: EventListener + private val onAdBreakEnded: EventListener init { val playerData = PlayerData() @@ -95,11 +95,11 @@ class GemiusAdapter( onAddVideoTrack = EventListener { event -> handleAddVideoTrack(event) } onRemoveVideoTrack = EventListener { event -> handleRemoveVideoTrack(event) } onVideoQualityChanged = EventListener { event -> handleVideoQualityChanged(event) } - onAdBreakBeginListener = EventListener { event -> handleAdBreakBegin(event) } - onAdBeginListener = EventListener { event -> handleAdBegin(event) } - onAdEndListener = EventListener { event -> handleAdEnd(event) } - onAdSkipListener = EventListener { event -> handleAdSkip(event) } - onAdBreakEndedListener = EventListener { event -> handleAdBreakEnded(event) } + onAdBreakBegin = EventListener { event -> handleAdBreakBegin(event) } + onAdBegin = EventListener { event -> handleAdBegin(event) } + onAdEnd = EventListener { event -> handleAdEnd(event) } + onAdSkip = EventListener { event -> handleAdSkip(event) } + onAdBreakEnded = EventListener { event -> handleAdBreakEnded(event) } addEventListeners() } @@ -125,11 +125,11 @@ class GemiusAdapter( playerView.player.addEventListener(PlayerEventTypes.VOLUMECHANGE, onVolumeChange) playerView.player.videoTracks.addEventListener(VideoTrackListEventTypes.ADDTRACK, onAddVideoTrack) playerView.player.videoTracks.addEventListener(VideoTrackListEventTypes.REMOVETRACK, onRemoveVideoTrack) - playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_BEGIN, onAdBreakBeginListener) - playerView.player.ads.addEventListener(AdsEventTypes.AD_BEGIN, onAdBeginListener) - playerView.player.ads.addEventListener(AdsEventTypes.AD_END, onAdEndListener) - playerView.player.ads.addEventListener(AdsEventTypes.AD_SKIP, onAdSkipListener) - playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_END, onAdBreakEndedListener) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_BEGIN, onAdBreakBegin) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BEGIN, onAdBegin) + playerView.player.ads.addEventListener(AdsEventTypes.AD_END, onAdEnd) + playerView.player.ads.addEventListener(AdsEventTypes.AD_SKIP, onAdSkip) + playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_END, onAdBreakEnded) } private fun handleSourceChange(event: SourceChangeEvent) { From 156916245b78d99da2a58c828aeec0f2e9a61f93 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:53:58 +0200 Subject: [PATCH 24/40] handle ad end --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 3183f56b..bd2c96c5 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -273,8 +273,14 @@ class GemiusAdapter( } private fun handleAdEnd(event: AdEndEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: id = ${event.ad?.id}") } + reportBasicEvent(Player.EventType.COMPLETE) + reportBasicEvent(Player.EventType.CLOSE) + adCount++ + currentAd = null + playerView.player.removeEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) + playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) } private fun handleAdSkip(event: AdSkipEvent) { if (configuration.debug) { From cb8a5626e249922a91641806a613f34360f543f1 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:54:45 +0200 Subject: [PATCH 25/40] handle ad skip --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index bd2c96c5..13636591 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -284,8 +284,9 @@ class GemiusAdapter( } private fun handleAdSkip(event: AdSkipEvent) { if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: id = ${event.ad?.id}") } + reportBasicEvent(Player.EventType.SKIP) } private fun handleAdBreakEnded(event: AdBreakEndEvent) { if (configuration.debug) { From 7fb1f2d33eee9effacfffeea544507dc8a0a3474 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 15:58:08 +0200 Subject: [PATCH 26/40] handle ad break end --- .../connector/analytics/gemius/GemiusAdapter.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 13636591..f1a4160d 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -289,9 +289,17 @@ class GemiusAdapter( reportBasicEvent(Player.EventType.SKIP) } private fun handleAdBreakEnded(event: AdBreakEndEvent) { + val offset = event.adBreak.timeOffset if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}") + Log.d(TAG, "Player Event: ${event.type}: offset = ${offset}") } + adCount = 1 + if (offset > 0) partCount++ + val programId = programId ?: return + val programData = programData ?: return + gemiusPlayer?.newProgram(programId, programData) + playerView.player.removeEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) + if (offset == 0) playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) } private fun reportBasicEvent(eventType: Player.EventType) { val programId = programId ?: return From 27b02463f66d91fbc51cd976d416e11a88a06a6c Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 16:02:25 +0200 Subject: [PATCH 27/40] dont report play if playing fired before preroll --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index f1a4160d..280569ea 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -161,6 +161,7 @@ class GemiusAdapter( adEventData.adPosition = adCount gemiusPlayer?.adEvent(programId, adId, offset, Player.EventType.PLAY, adEventData) } ?: run { + if (hasPrerollScheduled()) return val player = playerView.player val currentQuality = player.videoTracks.first { track -> track.isEnabled }.activeQuality val programEventData = EventProgramData() @@ -327,5 +328,9 @@ class GemiusAdapter( adData.resolution = "${playerView.width}x${playerView.height}" return adData } - } + } + + private fun hasPrerollScheduled(): Boolean { + return playerView.player.ads.scheduledAds.any { it.adBreak?.timeOffset == 0 } + } } \ No newline at end of file From a125eb1e66c9e04896e5a796cb1419da21fb82f4 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 16:04:50 +0200 Subject: [PATCH 28/40] use member variable --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 280569ea..da191484 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -317,7 +317,7 @@ class GemiusAdapter( private fun buildAdData(ad: Ad): AdData { val adData = AdData() val linearAd = ad as? LinearAd ?: return adData - configuration.adProcessor?.let { adProcessor -> + adProcessor?.let { adProcessor -> return adProcessor.apply(ad) } ?: run { adData.name = linearAd.id From b02bba39d31351485057df98143d6783647ab8d2 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 16:04:59 +0200 Subject: [PATCH 29/40] remove unused imports --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index da191484..4369d379 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -11,8 +11,6 @@ import com.gemius.sdk.stream.PlayerData import com.gemius.sdk.stream.ProgramData import com.theoplayer.android.api.ads.Ad import com.theoplayer.android.api.ads.LinearAd -import com.theoplayer.android.api.ads.ima.GoogleImaAd -import com.theoplayer.android.api.event.Event import com.theoplayer.android.api.event.EventListener import com.theoplayer.android.api.event.ads.AdBeginEvent import com.theoplayer.android.api.event.ads.AdBreakBeginEvent @@ -23,7 +21,6 @@ import com.theoplayer.android.api.event.ads.AdsEventTypes import com.theoplayer.android.api.event.player.EndedEvent import com.theoplayer.android.api.event.player.ErrorEvent import com.theoplayer.android.api.event.player.PauseEvent -import com.theoplayer.android.api.event.player.PlayEvent import com.theoplayer.android.api.event.player.PlayerEventTypes import com.theoplayer.android.api.event.player.PlayingEvent import com.theoplayer.android.api.event.player.SeekingEvent @@ -35,7 +32,6 @@ import com.theoplayer.android.api.event.track.mediatrack.video.VideoTrackEventTy import com.theoplayer.android.api.event.track.mediatrack.video.list.AddTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.VideoTrackListEventTypes -import com.theoplayer.android.api.event.track.tracklist.TrackListEvent import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality const val PLAYER_ID = "THEOplayer" From 3c2d61322d12660a4de2c41c116b05a036e0a53b Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 16:05:41 +0200 Subject: [PATCH 30/40] remove curly braces --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 4369d379..81821743 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -263,7 +263,7 @@ class GemiusAdapter( currentAd = ad val adId = ad?.id ?: return if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}: id = ${adId}") + Log.d(TAG, "Player Event: ${event.type}: id = $adId") } val adData = buildAdData(ad) gemiusPlayer?.newAd(adId,adData) @@ -288,7 +288,7 @@ class GemiusAdapter( private fun handleAdBreakEnded(event: AdBreakEndEvent) { val offset = event.adBreak.timeOffset if (configuration.debug) { - Log.d(TAG, "Player Event: ${event.type}: offset = ${offset}") + Log.d(TAG, "Player Event: ${event.type}: offset = $offset") } adCount = 1 if (offset > 0) partCount++ From 25717776d96a918ded1b5fceb890e5dfc72688fb Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 16:06:44 +0200 Subject: [PATCH 31/40] safe assert --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 81821743..137b1b08 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -236,7 +236,7 @@ class GemiusAdapter( Log.d(TAG, "Player Event: ${event.type}") } val programId = programId ?: return - val activeQuality = (event.getQuality() as VideoQuality) + val activeQuality = (event.quality as? VideoQuality) ?: return val height = activeQuality.height val width = activeQuality.width currentAd?.let { ad -> From f38cd29b731309fd0227f54b174c91ce174c6b0f Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 20:58:32 +0200 Subject: [PATCH 32/40] add log flags --- .../analytics/gemius/GemiusAdapter.kt | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 137b1b08..610386fc 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -2,6 +2,8 @@ package com.theoplayer.android.connector.analytics.gemius import android.content.Context import android.util.Log +import com.gemius.sdk.Config +import com.gemius.sdk.GemiusSdk import com.gemius.sdk.stream.AdData import com.gemius.sdk.stream.EventAdData import com.gemius.sdk.stream.EventProgramData @@ -37,6 +39,10 @@ import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality const val PLAYER_ID = "THEOplayer" const val TAG = "GemiusConnector" +const val GEMIUS_SDK_LOGS = true +const val PLAYER_EVENTS_LOGS = true +const val INTEGRATION_LOGS = true + class GemiusAdapter( context: Context, private val configuration: GemiusConfiguration, @@ -78,6 +84,7 @@ class GemiusAdapter( playerData.volume = computeVolume() gemiusPlayer = Player(PLAYER_ID, configuration.hitCollectorHost, configuration.gemiusId, playerData) gemiusPlayer.setContext(context) + Config.setLoggingEnabled(configuration.debug && GEMIUS_SDK_LOGS) onSourceChange = EventListener { event -> handleSourceChange(event) } onFirstPlaying = EventListener { event -> handleFirstPlaying(event) } @@ -129,7 +136,7 @@ class GemiusAdapter( } private fun handleSourceChange(event: SourceChangeEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: source = ${event.source.toString()}") } partCount = 1 @@ -141,7 +148,7 @@ class GemiusAdapter( playerView.player.addEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) } private fun handleFirstPlaying(event: PlayingEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } val computedVolume = computeVolume() @@ -170,38 +177,38 @@ class GemiusAdapter( } } private fun handlePause(event: PauseEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } reportBasicEvent(Player.EventType.PAUSE) } private fun handleWaiting(event: WaitingEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } reportBasicEvent(Player.EventType.BUFFER) } private fun handleSeeking(event: SeekingEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } reportBasicEvent(Player.EventType.SEEK) } private fun handleError(event: ErrorEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { val errorObject = event.errorObject Log.d(TAG, "Player Event: ${event.type}: error = ${errorObject.code}: ${errorObject.message}") } reportBasicEvent(Player.EventType.COMPLETE) } private fun handleEnded(event: EndedEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: currentTime = ${event.currentTime}") } reportBasicEvent(Player.EventType.COMPLETE) } private fun handleVolumeChange(event: VolumeChangeEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: volume = ${event.volume}") } val computedVolume = computeVolume() @@ -218,21 +225,21 @@ class GemiusAdapter( } } private fun handleAddVideoTrack(event: AddTrackEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event (Video Track): ${event.type}") } val track = event.track track.addEventListener(VideoTrackEventTypes.ACTIVEQUALITYCHANGEDEVENT, onVideoQualityChanged) } private fun handleRemoveVideoTrack(event: RemoveTrackEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}") } val track = event.track track.removeEventListener(VideoTrackEventTypes.ACTIVEQUALITYCHANGEDEVENT, onVideoQualityChanged) } private fun handleVideoQualityChanged(event: QualityChangedEvent<*,*>) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}") } val programId = programId ?: return @@ -251,7 +258,7 @@ class GemiusAdapter( } } private fun handleAdBreakBegin(event: AdBreakBeginEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: offset = ${event.adBreak.timeOffset}") } reportBasicEvent(Player.EventType.BREAK) @@ -262,14 +269,14 @@ class GemiusAdapter( val ad = event.ad currentAd = ad val adId = ad?.id ?: return - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: id = $adId") } val adData = buildAdData(ad) gemiusPlayer?.newAd(adId,adData) } private fun handleAdEnd(event: AdEndEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: id = ${event.ad?.id}") } reportBasicEvent(Player.EventType.COMPLETE) @@ -280,14 +287,14 @@ class GemiusAdapter( playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) } private fun handleAdSkip(event: AdSkipEvent) { - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: id = ${event.ad?.id}") } reportBasicEvent(Player.EventType.SKIP) } private fun handleAdBreakEnded(event: AdBreakEndEvent) { val offset = event.adBreak.timeOffset - if (configuration.debug) { + if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: offset = $offset") } adCount = 1 From 9c9f00d2a6f46b6b8df9ff4602ab5be9f3bc67af Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 21:27:34 +0200 Subject: [PATCH 33/40] integration points logs --- .../analytics/gemius/GemiusAdapter.kt | 53 +++++++++++++++++-- .../connector/analytics/gemius/Utils.kt | 23 ++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/Utils.kt diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 610386fc..05237b74 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -35,6 +35,7 @@ import com.theoplayer.android.api.event.track.mediatrack.video.list.AddTrackEven import com.theoplayer.android.api.event.track.mediatrack.video.list.RemoveTrackEvent import com.theoplayer.android.api.event.track.mediatrack.video.list.VideoTrackListEventTypes import com.theoplayer.android.api.player.track.mediatrack.quality.VideoQuality +import com.theoplayer.android.connector.analytics.gemius.Utils.describeEvent const val PLAYER_ID = "THEOplayer" const val TAG = "GemiusConnector" @@ -143,6 +144,10 @@ class GemiusAdapter( currentAd = null val programId = this.programId ?: return val programData = this.programData ?: return + + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: NEW PROGRAM - id: $programId - data: ${programData}") + } gemiusPlayer?.newProgram(programId,programData) playerView.player.removeEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) playerView.player.addEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) @@ -162,6 +167,9 @@ class GemiusAdapter( adEventData.breakSize = adBreak.ads.size if (ad is LinearAd) adEventData.adDuration = ad.duration adEventData.adPosition = adCount + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: AD EVENT (${describeEvent(Player.EventType.PLAY)}) - programId: $programId - adId: $adId - offset: $offset") + } gemiusPlayer?.adEvent(programId, adId, offset, Player.EventType.PLAY, adEventData) } ?: run { if (hasPrerollScheduled()) return @@ -173,7 +181,11 @@ class GemiusAdapter( programEventData.partID = partCount programEventData.autoPlay = player.isAutoplay if (currentQuality!= null) programEventData.quality = "${currentQuality.width}x${currentQuality.height}" - gemiusPlayer?.programEvent(programId, player.currentTime.toInt(), Player.EventType.PLAY, programEventData) + val currentTime = player.currentTime.toInt() + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: PROGRAM EVENT (${describeEvent(Player.EventType.PLAY)}) - programId: $programId - offset: $currentTime") + } + gemiusPlayer?.programEvent(programId, currentTime, Player.EventType.PLAY, programEventData) } } private fun handlePause(event: PauseEvent) { @@ -215,13 +227,22 @@ class GemiusAdapter( val programId = programId ?: return currentAd?.let { ad -> val adBreak = ad.adBreak ?: return + val adId = ad.id + val offset = adBreak.timeOffset val adEventData = EventAdData() adEventData.volume = computedVolume - gemiusPlayer?.adEvent(programId, ad.id, adBreak.timeOffset, Player.EventType.CHANGE_VOL, adEventData) + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: AD EVENT (${describeEvent(Player.EventType.CHANGE_VOL)}) - programId: $programId - adId: $adId - offset: $offset") + } + gemiusPlayer?.adEvent(programId, ad.id, offset, Player.EventType.CHANGE_VOL, adEventData) } ?: run { val programEventData = EventProgramData() programEventData.volume = computedVolume - gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), Player.EventType.CHANGE_VOL, programEventData) + val currentTime = playerView.player.currentTime.toInt() + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: PROGRAM EVENT (${describeEvent(Player.EventType.CHANGE_VOL)}) - programId: $programId - offset: $currentTime") + } + gemiusPlayer?.programEvent(programId, currentTime, Player.EventType.CHANGE_VOL, programEventData) } } private fun handleAddVideoTrack(event: AddTrackEvent) { @@ -248,13 +269,22 @@ class GemiusAdapter( val width = activeQuality.width currentAd?.let { ad -> val adBreak = ad.adBreak ?: return + val adId = ad.id + val offset = adBreak.timeOffset val adEventData = EventAdData() adEventData.quality = "${width}x${height}" + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: AD EVENT (${describeEvent(Player.EventType.CHANGE_QUAL)}) - programId: $programId - adId: $adId - offset: $offset") + } gemiusPlayer?.adEvent(programId,ad.id,adBreak.timeOffset,Player.EventType.CHANGE_QUAL,adEventData) } ?: run { val programEventData = EventProgramData() programEventData.quality = "${width}x${height}" - gemiusPlayer?.programEvent(programId,playerView.player.currentTime.toInt(),Player.EventType.CHANGE_QUAL,programEventData) + val currentTime = playerView.player.currentTime.toInt() + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: PROGRAM EVENT (${describeEvent(Player.EventType.CHANGE_QUAL)}) - programId: $programId - offset: $currentTime") + } + gemiusPlayer?.programEvent(programId,currentTime,Player.EventType.CHANGE_QUAL,programEventData) } } private fun handleAdBreakBegin(event: AdBreakBeginEvent) { @@ -273,6 +303,9 @@ class GemiusAdapter( Log.d(TAG, "Player Event: ${event.type}: id = $adId") } val adData = buildAdData(ad) + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: NEW AD - id: $adId - data: $adData") + } gemiusPlayer?.newAd(adId,adData) } private fun handleAdEnd(event: AdEndEvent) { @@ -301,6 +334,9 @@ class GemiusAdapter( if (offset > 0) partCount++ val programId = programId ?: return val programData = programData ?: return + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: NEW PROGRAM - id: $programId - data: $programData") + } gemiusPlayer?.newProgram(programId, programData) playerView.player.removeEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) if (offset == 0) playerView.player.addEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) @@ -309,11 +345,18 @@ class GemiusAdapter( val programId = programId ?: return currentAd?.let { ad -> val offset = ad.adBreak?.timeOffset ?: return + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: AD EVENT (${describeEvent(eventType)}) - id: ${ad.id} - offset: $offset") + } // docs mention null can be passed but interface prohibits gemiusPlayer?.adEvent(programId,ad.id, offset, eventType, EventAdData()) } ?: run { + val currentTime = playerView.player.currentTime.toInt() + if (configuration.debug && INTEGRATION_LOGS) { + Log.d(TAG, "Integration: PROGRAM EVENT (${describeEvent(eventType)}) - id: $programId - offset: $currentTime") + } // docs mention null can be passed but interface prohibits - gemiusPlayer?.programEvent(programId, playerView.player.currentTime.toInt(), eventType, EventProgramData()) + gemiusPlayer?.programEvent(programId, currentTime, eventType, EventProgramData()) } } diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/Utils.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/Utils.kt new file mode 100644 index 00000000..83faea0a --- /dev/null +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/Utils.kt @@ -0,0 +1,23 @@ +package com.theoplayer.android.connector.analytics.gemius + +import com.gemius.sdk.stream.Player + +object Utils { + fun describeEvent(eventType: Player.EventType): String = when (eventType) { + Player.EventType.SKIP -> "SKIP" + Player.EventType.PLAY -> "PLAY" + Player.EventType.PAUSE -> "PAUSE" + Player.EventType.STOP -> "STOP" + Player.EventType.CLOSE -> "CLOSE" + Player.EventType.BUFFER -> "BUFFER" + Player.EventType.BREAK -> "BREAK" + Player.EventType.SEEK -> "SEEK" + Player.EventType.COMPLETE -> "COMPLETE" + Player.EventType.NEXT -> "NEXT" + Player.EventType.PREV -> "PREV" + Player.EventType.CHANGE_VOL -> "CHANGE_VOL" + Player.EventType.CHANGE_QUAL -> "CHANGE_QUAL" + Player.EventType.CHANGE_RES -> "CHANGE_RES" + else -> "UNKNOWN EVENTTYPE" + } +} \ No newline at end of file From 7ce572026df7a31b084b57b9daf4d7a122b9a4fa Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 21:29:29 +0200 Subject: [PATCH 34/40] remove curly braces --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 05237b74..8d77b3bd 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -146,7 +146,7 @@ class GemiusAdapter( val programData = this.programData ?: return if (configuration.debug && INTEGRATION_LOGS) { - Log.d(TAG, "Integration: NEW PROGRAM - id: $programId - data: ${programData}") + Log.d(TAG, "Integration: NEW PROGRAM - id: $programId - data: $programData") } gemiusPlayer?.newProgram(programId,programData) playerView.player.removeEventListener(PlayerEventTypes.PLAYING,onFirstPlaying) From 5768abe2d232d19b4d1cf91da57252020f3120f9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 21 Jul 2025 21:29:56 +0200 Subject: [PATCH 35/40] remove unused import --- .../android/connector/analytics/gemius/GemiusAdapter.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index 8d77b3bd..a8a19e5e 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -3,7 +3,6 @@ package com.theoplayer.android.connector.analytics.gemius import android.content.Context import android.util.Log import com.gemius.sdk.Config -import com.gemius.sdk.GemiusSdk import com.gemius.sdk.stream.AdData import com.gemius.sdk.stream.EventAdData import com.gemius.sdk.stream.EventProgramData From 06ff3ffb97bd1faf76a3e9442e927bf12e856b90 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Tue, 22 Jul 2025 09:32:09 +0200 Subject: [PATCH 36/40] test --- .../android/connector/MainActivity.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/app/src/main/java/com/theoplayer/android/connector/MainActivity.kt b/app/src/main/java/com/theoplayer/android/connector/MainActivity.kt index 29778b9e..35e81eb5 100644 --- a/app/src/main/java/com/theoplayer/android/connector/MainActivity.kt +++ b/app/src/main/java/com/theoplayer/android/connector/MainActivity.kt @@ -35,6 +35,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog +import com.gemius.sdk.stream.ProgramData import com.theoplayer.android.api.THEOplayerConfig import com.theoplayer.android.api.THEOplayerView import com.theoplayer.android.api.ads.LinearAd @@ -50,7 +51,9 @@ import com.theoplayer.android.connector.analytics.comscore.ComscoreMediaType import com.theoplayer.android.connector.analytics.comscore.ComscoreMetaData import com.theoplayer.android.connector.analytics.conviva.ConvivaConfiguration import com.theoplayer.android.connector.analytics.conviva.ConvivaConnector +import com.theoplayer.android.connector.analytics.gemius.GemiusConfiguration import com.theoplayer.android.connector.analytics.nielsen.NielsenConnector +import com.theoplayer.android.connector.analytics.gemius.GemiusConnector import com.theoplayer.android.connector.uplynk.SkippedAdStrategy import com.theoplayer.android.connector.uplynk.UplynkConfiguration import com.theoplayer.android.connector.uplynk.UplynkConnector @@ -74,6 +77,7 @@ class MainActivity : ComponentActivity() { private lateinit var comscoreConnector: ComscoreConnector private lateinit var yospaceConnector: YospaceConnector private lateinit var uplynkConnector: UplynkConnector + private lateinit var gemiusConnector: GemiusConnector override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -85,6 +89,7 @@ class MainActivity : ComponentActivity() { setupNielsen() setupYospace() setupUplynk() + setupGemius() setupAdListeners() setContent { @@ -184,6 +189,26 @@ class MainActivity : ComponentActivity() { ) } + private fun setupGemius() { + val gemiusId = "your_gemius_id" + val hitCollectorHost = "your_hit_collector_host" + val gemiusConfiguration = GemiusConfiguration( + "Demo", + "1.0", + hitCollectorHost, + gemiusId, + true, + null + ) + gemiusConnector = GemiusConnector(this,gemiusConfiguration,theoplayerView) + val programData = ProgramData() + programData.name = "testasset1" + programData.programGenre = 1 + programData.programSeason = "1" + programData.programProducer = "Someone" + gemiusConnector.update("test asset 1", programData) + } + private fun setupNielsen() { val appId = "your_nielsen_app_id" nielsenConnector = NielsenConnector(applicationContext, theoplayerView.player, appId, true) From 7608c172d3251f478b1c6860e38b4a6ff2096a7d Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Tue, 22 Jul 2025 09:32:28 +0200 Subject: [PATCH 37/40] add gemius connector dependency --- app/build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 405b4e34..41c1b751 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,6 +69,8 @@ dependencies { implementation project(':connectors:analytics:comscore') implementation libs.comscore + implementation project(":connectors:analytics:gemius") + implementation project(':connectors:yospace') implementation libs.yospace From 409bc2b96e6403bd4f785131347710ea739283d6 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Tue, 22 Jul 2025 09:38:39 +0200 Subject: [PATCH 38/40] add missing dependencies --- app/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/build.gradle b/app/build.gradle index 41c1b751..36e0eeaa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,6 +56,9 @@ dependencies { implementation libs.androidx.compose.ui.tooling.preview debugImplementation libs.androidx.compose.ui.tooling + implementation "ch.acra:acra-http:5.7.0" + implementation fileTree(dir: './libs/GemiusSDK_2.0.8.aar', include: ['*.aar', '*.jar'], exclude: []) + implementation "com.theoplayer.theoplayer-sdk-android:core:$sdkVersion" implementation "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:$sdkVersion" implementation libs.theoplayer.android.ui From 03a696fc1bc23068abc0edb5e16a09989d356713 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Mon, 4 Aug 2025 15:33:15 +0200 Subject: [PATCH 39/40] Pass gemiusSdkDir as gradle property --- app/libs/.gitignore | 1 + connectors/analytics/gemius/build.gradle | 13 ++++++++++++- gradle.properties | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 app/libs/.gitignore diff --git a/app/libs/.gitignore b/app/libs/.gitignore new file mode 100644 index 00000000..6d81fcdb --- /dev/null +++ b/app/libs/.gitignore @@ -0,0 +1 @@ +*.aar diff --git a/connectors/analytics/gemius/build.gradle b/connectors/analytics/gemius/build.gradle index 12c0b13c..23ee7420 100644 --- a/connectors/analytics/gemius/build.gradle +++ b/connectors/analytics/gemius/build.gradle @@ -29,12 +29,23 @@ android { } } +// The Gemius SDK location should be set by the app and passed in a gemiusSdkDir property. +def gemiusSdkDir = rootProject.properties['gemiusSdkDir'] +if (!gemiusSdkDir) { + logger.warn("⚠️ WARNING: gemiusSdkDir not set.") +} else if (!rootProject.file(gemiusSdkDir).exists()) { + logger.warn("⚠️ WARNING: gemiusSdkDir does not exist at: ${gemiusSdkDir}") +} else { + dependencies { + compileOnly files("${rootProject.file(gemiusSdkDir)}/GemiusSDK_2.0.8.aar") + } +} + dependencies { implementation libs.androidx.core.ktx implementation libs.androidx.appcompat implementation libs.material - compileOnly fileTree(dir: './libs/GemiusSDK_2.0.8.aar', include: ['*.aar', '*.jar'], exclude: []) compileOnly "com.theoplayer.theoplayer-sdk-android:core:$sdkVersion" compileOnly "com.theoplayer.theoplayer-sdk-android:integration-ads-ima:$sdkVersion" testImplementation libs.junit diff --git a/gradle.properties b/gradle.properties index 22f41cdc..da0a1706 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,3 +26,5 @@ android.nonFinalResIds=true groupId=com.theoplayer.android-connector sdkVersion=9.8.2 connectorVersion=9.8.2 + +gemiusSdkDir=./app/libs \ No newline at end of file From f0876c0062fda11f193b5cac85f93796cd1ed982 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Thu, 7 Aug 2025 14:21:09 +0200 Subject: [PATCH 40/40] Add destroy method --- .../analytics/gemius/GemiusAdapter.kt | 23 +++++++++++++++++++ .../analytics/gemius/GemiusConnector.kt | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt index a8a19e5e..6d629998 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusAdapter.kt @@ -112,6 +112,10 @@ class GemiusAdapter( this.programData = programData } + fun destroy() { + removeEventListeners() + } + private fun computeVolume(): Int { return if (playerView.player.isMuted) -1 else (playerView.player.volume * 100).toInt() } @@ -135,6 +139,25 @@ class GemiusAdapter( playerView.player.ads.addEventListener(AdsEventTypes.AD_BREAK_END, onAdBreakEnded) } + private fun removeEventListeners() { + playerView.player.removeEventListener(PlayerEventTypes.SOURCECHANGE, onSourceChange) + playerView.player.removeEventListener(PlayerEventTypes.PLAYING, onFirstPlaying) +// playerView.player.removeEventListener(PlayerEventTypes.PLAY, onPlay) + playerView.player.removeEventListener(PlayerEventTypes.PAUSE, onPause) + playerView.player.removeEventListener(PlayerEventTypes.WAITING, onWaiting) + playerView.player.removeEventListener(PlayerEventTypes.SEEKING, onSeeking) + playerView.player.removeEventListener(PlayerEventTypes.ERROR, onError) + playerView.player.removeEventListener(PlayerEventTypes.ENDED, onEnded) + playerView.player.removeEventListener(PlayerEventTypes.VOLUMECHANGE, onVolumeChange) + playerView.player.videoTracks.removeEventListener(VideoTrackListEventTypes.ADDTRACK, onAddVideoTrack) + playerView.player.videoTracks.removeEventListener(VideoTrackListEventTypes.REMOVETRACK, onRemoveVideoTrack) + playerView.player.ads.removeEventListener(AdsEventTypes.AD_BREAK_BEGIN, onAdBreakBegin) + playerView.player.ads.removeEventListener(AdsEventTypes.AD_BEGIN, onAdBegin) + playerView.player.ads.removeEventListener(AdsEventTypes.AD_END, onAdEnd) + playerView.player.ads.removeEventListener(AdsEventTypes.AD_SKIP, onAdSkip) + playerView.player.ads.removeEventListener(AdsEventTypes.AD_BREAK_END, onAdBreakEnded) + } + private fun handleSourceChange(event: SourceChangeEvent) { if (configuration.debug && PLAYER_EVENTS_LOGS) { Log.d(TAG, "Player Event: ${event.type}: source = ${event.source.toString()}") diff --git a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt index 0d907aa6..cc3c4b27 100644 --- a/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt +++ b/connectors/analytics/gemius/src/main/java/com/theoplayer/android/connector/analytics/gemius/GemiusConnector.kt @@ -20,4 +20,8 @@ class GemiusConnector( fun update(programId: String, programData: ProgramData) { gemiusAdapter.update(programId, programData) } + + fun destroy() { + gemiusAdapter.destroy() + } } \ No newline at end of file