Media analytics
What you learn​
You're instantiating DIVA Player in your Android app and relying on DIVA Back Office as the video streaming source.
The goal of this article is to build the simplest Android app to stream a video from the DIVA Back Office with active Conviva and Youbora media analytics.
Before starting​
- Ensure the DIVA Back Office instance you rely on is up and running.
- Ask your video engineers team
<videoId>
,<settingsURL>
,<languageCountryCode>
,<userToken>
and<sharedKey>
. - Ensure the settings file contains the
mediaAnalytics
section:Based on your project requirements, the settings file only contains either the Conviva or Youbora configuration."mediaAnalytics": {
"conviva": {
"enabled": true,
"customerKey": "<yourCustomerKey>",
"playerName": "Diva",
"viewerId": "<yourViewerIdentifier>",
"cdnName": "Akamai",
"touchstoneUrl": "https://<yourSubdomain>.conviva.com"
},
"youbora": {
"enabled": true,
"playerName": "Diva",
"cdnName": "<yourCDNName>",
"userName": "<yourViewerIdentifier>",
"accountCode": "<yourAccountCode>"
}
}
Instantiation​
Media analytics code​
Enrich the Basic instantiation code with an instance of DivaExtraParams
(on TV) or DivaExtraParamsMobile
(on mobile) where to set:
divaListener
: ADivaListener
instance including theonAnalyticsCallback
callback for media analytics events. Add in theonAnalyticsCallback
implementation your business logic when specific events are sent to the media analytics provider.analyticsCustomTagGenerator
: Custom tag generator.analyticsCustomContentDimensionGenerator
: Custom dimensions.
Code sample​
Write the media analytics configuration in the Diva Extra paramenters object:
Mobile specific code​
val divaExtraParams = DivaExtraParamsMobile(
divaListener = object : DivaListener {
override fun onAnalyticsCallback(event: AnalyticsEvent) {
// Handle the analytics event
}
},
analyticsCustomTagGenerator = {
mapOf(
"tag1Name" to "<tag1Name>",
"tagNName" to "<tagNName>"
)
},
analyticsCustomContentDimensionGenerator = {
arrayListOf("<dimension1>", "<dimensionN>")
}
)
TV specific code​
val divaExtraParams = DivaExtraParams(
divaListener = object : DivaListener {
override fun onAnalyticsCallback(event: AnalyticsEvent) {
// Handle the analytics event
}
override fun onAudioTrackSelected(track: String) {
// You can leave empty this listener
}
override fun onClosedCaptionTrackSelected(track: String) {
// You can leave empty this listener
}
override fun onCustomActionResponse(payload: CustomActionPayload) {
// You can leave empty this listener
}
override fun onExit() {
// You can leave empty this listener
}
override fun onPlayerPosition(relativePosition: Long, absolutePosition: Date) {
// You can leave empty this listener
}
override fun onVideoError(error: VideoError, videoMetadata: VideoMetadataClean) {
// You can leave empty this listener
}
},
analyticsCustomTagGenerator = {
mapOf(
"tag1Name" to "<tag1Name>",
"tagNName" to "<tagNName>"
)
},
analyticsCustomContentDimensionGenerator = {
arrayListOf("<dimension1>", "<dimensionN>")
}
)
Note: You must implement all the DivaListener
methods even if others than onAnalyticsCallback
don't matter for media analytics.
Eventually, feed the DIVA Player instantiation with the divaExtraParams
parameter:
val boAdapter = DivaBoAdapter(this /*refers to the Activity class */, lifecycleScope)
boAdapter.createDivaFragment(
adapterSettingsUrl = <settingsURL>,
langCountryCode = <languageCountryCode>,
videoId = <videoId>,
getCurrentUserAccountAccessToken = {
//Get the user token
<userToken>
},
sharedKey = <sharedKey>
conf = divaExtraParams,
onError = { exception ->
//On Error
}) { divaFragment ->
supportFragmentManager
.beginTransaction()
.replace(R.id.fragment_container_view, divaFragment)
.commit()
}
Working sample code​
package com.example.divaplayerhelloworld20
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.deltatre.divaboadapter.DivaBoAdapter
import com.deltatre.divaboadapter.DivaExtraParams
import androidx.lifecycle.lifecycleScope
import com.deltatre.divacorelib.api.DivaListener
import com.deltatre.divacorelib.api.model.CustomActionPayload
import com.deltatre.divacorelib.api.player.PlayerAction
import com.deltatre.divacorelib.api.player.PlayerCallback
import com.deltatre.divacorelib.api.player.PlayerCommands
import com.deltatre.divacorelib.api.player.PlayerPosition
import com.deltatre.divacorelib.data.analytics.AnalyticsEvent
import com.deltatre.divacorelib.exceptions.VideoError
import com.deltatre.divacorelib.models.State
import com.deltatre.divacorelib.models.VideoMetadataClean
import java.util.Date
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val divaExtraParams = DivaExtraParams(
divaListener = object : DivaListener {
override fun onAnalyticsCallback(event: AnalyticsEvent) {
// Handle the analytics event
}
override fun onAudioTrackSelected(track: String) {
// You can leave empty this listener
}
override fun onClosedCaptionTrackSelected(track: String) {
// You can leave empty this listener
}
override fun onCustomActionResponse(payload: CustomActionPayload) {
// You can leave empty this listener
}
override fun onExit() {
// You can leave empty this listener
}
override fun onPlayerPosition(relativePosition: Long, absolutePosition: Date) {
// You can leave empty this listener
}
override fun onVideoError(error: VideoError, videoMetadata: VideoMetadataClean) {
// You can leave empty this listener
}
},
analyticsCustomTagGenerator = {
mapOf(
"tag1Name" to "<tag1Name>",
"tagNName" to "<tagNName>"
)
},
analyticsCustomContentDimensionGenerator = {
arrayListOf("<dimension1>", "<dimensionN>")
}
)
val boAdapter = DivaBoAdapter(this /*refers to the Activity class */, lifecycleScope)
boAdapter.createDivaFragment(
adapterSettingsUrl = "https://divademo.deltatre.net/DIVAProduct/www/Data/Diva5.xTest/settings/dyn/android.json",
langCountryCode = "en-US",
videoId = "bae2c2aa-0f4e-4113-8f33-ce41b6267cc9",
getCurrentUserAccountAccessToken = {
//Get the user token
""
},
sharedKey = "testpassword",
conf = divaExtraParams,
onError = { exception ->
//On Error
}) { divaFragment ->
supportFragmentManager
.beginTransaction()
.replace(R.id.fragment_container_view, divaFragment)
.commit()
}
}
}