11package com.segment.analytics.kotlin.destinations.nielsendtvr
22
3+ import android.content.Context
4+ import com.nielsen.app.sdk.AppSdk
35import com.segment.analytics.kotlin.core.*
46import com.segment.analytics.kotlin.core.platform.DestinationPlugin
57import com.segment.analytics.kotlin.core.platform.Plugin
8+ import com.segment.analytics.kotlin.core.platform.plugins.logger.log
9+ import com.segment.analytics.kotlin.core.utilities.toContent
10+ import kotlinx.serialization.Serializable
11+ import kotlinx.serialization.json.JsonObject
12+ import org.json.JSONException
13+ import org.json.JSONObject
14+ import java.util.*
615
716class NielsenDTVRDestination : DestinationPlugin () {
8- override val key: String = " Nielsen DTVR"
17+ companion object {
18+ private const val NIELSEN_DCR_FULL_KEY = " Nielsen DTVR"
19+ }
20+
21+ private var previousID3: String = " "
22+ internal var nielsenDTVRSettings: NielsenDTVRSettings ? = null
23+ internal lateinit var appSdk: AppSdk
24+ internal var id3EventNames: ArrayList <String > = arrayListOf ()
25+ private var id3PropertyName: String = " "
26+
27+ override val key: String = NIELSEN_DCR_FULL_KEY
928
1029 override fun update (settings : Settings , type : Plugin .UpdateType ) {
1130 super .update(settings, type)
31+ this .nielsenDTVRSettings =
32+ settings.destinationSettings(key, NielsenDTVRSettings .serializer())
1233 if (type == Plugin .UpdateType .Initial ) {
34+ if (nielsenDTVRSettings != null ) {
35+ setupNielsenAppSdk()
36+ id3EventNames = parseId3EventNames()
37+ id3PropertyName = nielsenDTVRSettings!! .id3Property.ifEmpty { " id3" }
38+ }
39+ }
40+ }
41+
42+ override fun track (payload : TrackEvent ): BaseEvent {
43+ if (! EventVideoEnum .isVideoEvent(payload.event)) {
44+ analytics.log(" Event is not Video" )
45+ return payload
46+ }
47+ val nielsenProperties: Map <String , String > = payload.properties.asStringMap()
48+ when (EventVideoEnum [payload.event]) {
49+ EventVideoEnum .ContentStarted -> {
50+ play(nielsenProperties)
51+ loadMetadata(nielsenProperties)
52+ }
53+ EventVideoEnum .PlaybackResumed ,
54+ EventVideoEnum .PlaybackSeekCompleted ,
55+ EventVideoEnum .PlaybackBufferCompleted -> {
56+ play(nielsenProperties)
57+ }
58+ EventVideoEnum .PlaybackPaused ,
59+ EventVideoEnum .PlaybackInterrupted ,
60+ EventVideoEnum .ContentCompleted ,
61+ EventVideoEnum .PlaybackBufferStarted ,
62+ EventVideoEnum .PlaybackSeekStarted ,
63+ // Nielsen requested Video Playback Completed and new Video Playback Exited event map to stop as end is not used for DTVR
64+ EventVideoEnum .PlaybackExited ,
65+ EventVideoEnum .PlaybackCompleted -> {
66+ stop()
67+ }
68+ EventVideoEnum .ApplicationBackgrounded -> {
69+ stop()
70+ }
71+ else -> {
72+ analytics.log(" Video Event not found" )
73+ }
74+ }
75+ if (id3EventNames.contains(payload.event.lowercase(Locale .getDefault()))) {
76+ sendID3(nielsenProperties)
77+ }
78+ return payload
79+ }
80+
81+ /* *
82+ * creating Nielsen App SDK.
83+ */
84+ private fun setupNielsenAppSdk () {
85+ var sfcode = " us"
86+ if (! nielsenDTVRSettings!! .sfCode.isNullOrEmpty()) {
87+ sfcode = nielsenDTVRSettings!! .sfCode!!
88+ }
89+ // Create AppSdk configuration object (JSONObject)
90+ val appSdkConfig: JSONObject = JSONObject ()
91+ .put(" appid" , nielsenDTVRSettings!! .appId)
92+ .put(" sfcode" , sfcode)
93+ if (nielsenDTVRSettings!! .debug) {
94+ appSdkConfig.put(" nol_devDebug" , " DEBUG" )
95+ }
96+ appSdk = AppSdk (analytics.configuration.application as Context , appSdkConfig, null )
97+ analytics.log(" new AppSdk(${appSdkConfig.toString(2 )} )" )
98+ }
99+
100+ /* *
101+ * retrieves lowercase list of id3 event names from settings
102+ *
103+ * @return list of lower case id3 event names
104+ */
105+ private fun parseId3EventNames (): ArrayList <String > {
106+ val id3EventNames = ArrayList <String >()
107+ id3EventNames.addAll(nielsenDTVRSettings!! .sendId3Events)
108+ for (i in id3EventNames.indices) {
109+ id3EventNames[i] = id3EventNames[i].lowercase(Locale .getDefault())
110+ }
111+ return id3EventNames
112+ }
113+
114+ /* *
115+ * Creating Metadata in JSONObject type. JSON value must be string value. And send it to neilsen SDK
116+ * @param nielsenProperties Map<String, String> properties from payload of the Segment track event
117+ */
118+ private fun loadMetadata (nielsenProperties : Map <String , String >) {
119+ val jsonMetadata = JSONObject ()
120+ try {
121+ jsonMetadata.put(" type" , " content" )
122+ if (nielsenProperties.containsKey(" channel" )) {
123+ jsonMetadata.put(" channelName" , nielsenProperties[" channel" ])
124+ }
125+ var loadType = " "
126+ if (nielsenProperties.containsKey(" load_type" )) {
127+ loadType = " load_type"
128+ }
129+ if (nielsenProperties.containsKey(" loadType" )) {
130+ loadType = " loadType"
131+ }
132+ if (loadType.isNotEmpty()) {
133+ jsonMetadata.put(
134+ " adModel" ,
135+ if (nielsenProperties[loadType].equals(" dynamic" )) " 2" else " 1"
136+ )
137+ }
138+ } catch (e: JSONException ) {
139+ analytics.log(" Failed to send loadMetadata event : $e " )
140+ }
141+ analytics.log(" appSdk.loadMetadata($jsonMetadata )" )
142+ appSdk.loadMetadata(jsonMetadata)
143+ }
144+
145+ /* *
146+ * a method to sendID3 value to NeilsenSDK
147+ * @param nielsenProperties Map<String, String> properties from payload of the Segment track event
148+ */
149+ private fun sendID3 (nielsenProperties : Map <String , String >) {
150+ val id3: String? = nielsenProperties[id3PropertyName]
151+ if (id3.isNullOrEmpty() || previousID3 == id3)
152+ return
153+ previousID3 = id3
154+ analytics.log(" appSdk.sendID3$id3 )" )
155+ appSdk.sendID3(id3)
156+ }
157+
158+ private fun play (nielsenProperties : Map <String , String >) {
159+ val channelInfo = JSONObject ()
160+ try {
161+ if (nielsenProperties.containsKey(" channel" )) {
162+ channelInfo.put(" channelName" , nielsenProperties[" channel" ])
163+ }
164+ } catch (e: JSONException ) {
165+ analytics.log( " Failed to send play event : $e " )
13166 }
167+ analytics.log(" appSdk.play($channelInfo )" )
168+ appSdk.play(channelInfo)
169+ }
170+
171+ private fun stop () {
172+ analytics.log(" appSdk.stop()" )
173+ appSdk.stop()
14174 }
175+ }
176+
177+ internal enum class EventVideoEnum (
178+ /* *
179+ * Retrieves the Neilsen DCR video event name. This is different from `enum.name()`
180+ *
181+ * @return Event name.
182+ */
183+ val eventName : String
184+ ) {
185+ PlaybackPaused (" Video Playback Paused" ),
186+ PlaybackResumed (" Video Playback Resumed" ),
187+ PlaybackExited (" Video Playback Exited" ),
188+ PlaybackInterrupted (" Video Playback Interrupted" ),
189+ PlaybackCompleted (" Video Playback Completed" ),
190+ ContentStarted (" Video Content Started" ),
191+ ContentCompleted (" Video Content Completed" ),
192+ PlaybackBufferStarted (" Video Playback Buffer Started" ),
193+ PlaybackBufferCompleted (" Video Playback Buffer Completed" ),
194+ PlaybackSeekStarted (" Video Playback Seek Started" ),
195+ PlaybackSeekCompleted (" Video Playback Seek Completed" ),
196+ ApplicationBackgrounded (" Application Backgrounded" );
197+
198+ companion object {
199+ private var names: MutableMap <String , EventVideoEnum >? = null
200+
201+ init {
202+ names = HashMap ()
203+ for (e in values()) {
204+ (names as HashMap <String , EventVideoEnum >)[e.eventName] = e
205+ }
206+ }
15207
16- override fun track (payload : TrackEvent ): BaseEvent ? {
17- return super .track(payload)
208+ operator fun get (name : String ): EventVideoEnum ? {
209+ if (names!! .containsKey(name)) {
210+ return names!! [name]
211+ }
212+ throw IllegalArgumentException (" $name is not a valid video event" )
213+ }
214+ /* *
215+ * Identifies if the event is a video event.
216+ *
217+ * @param eventName Event name
218+ * @return `true` if it's a video event, `false` otherwise.
219+ */
220+ fun isVideoEvent (eventName : String ): Boolean {
221+ return names!! .containsKey(eventName)
222+ }
18223 }
224+ }
225+ /* *
226+ * NielsenDTVR Settings data class.
227+ */
228+ @Serializable
229+ internal data class NielsenDTVRSettings (
230+ var appId : String ,
231+ var debug : Boolean ,
232+ var sfCode : String? ,
233+ var sendId3Events : ArrayList <String > = arrayListOf(),
234+ var id3Property : String = " id3" )
235+
236+ private fun JsonObject.asStringMap (): Map <String , String > = this .mapValues { (_, value) ->
237+ value.toContent().toString()
19238}
0 commit comments