Digital Measurement Video AndroidTV

From Engineering Client Portal

Engineering Portal / Digital/ DCR & DTVR / Digital Measurement Video AndroidTV

Introduction

This guide provides step-by-step instructions for integrating the Nielsen Android AppSDK into Android TV application.

The SDK supports three measurement types: DCR  (Digital Content Ratings) Video for measuring VOD and live streaming video content by tracking playhead positions during playback, DCR Static for measuring non-video content such as web views, articles, and informational screens, and DTVR (Digital TV Ratings) for measuring live streams by processing Nielsen ID3 tags watermarks embedded in the broadcast signal.

Android AppSDK Integration into Android TV App

The below steps cover the complete integration process including AppSDK initialization, metadata ingestion, playhead tracking, ID3 tag processing and user opt-out/opt-in implementation.

Step 1: Adding Nielsen AppSDK Dependency

Add the Nielsen Android AppSDK Jar maven dependency to the Application module within the build.gradle file.

In the app-level configuration file (build.gradle), add the below dependencies.

dependencies {
    implementation 'com.nielsenappsdk.global:ad:10.2.0.0'
    implementation 'com.google.android.gms:play-services-ads-identifier:18.2.0'
    implementation "androidx.work:work-runtime:2.11.2"
}

Step 2: Configuring AppSDK Initialization Parameters

Build the JSON object by providing required values (App ID and Debug level).

val config = JSONObject()
    .put("appid", "NIELSEN_APP_ID")         // Nielsen-provided App ID  [required]
    .put("nol_devDebug", "DEBUG")           // only for debug builds

Step 3: Initializing AppSDK

The following example code is for creating a singleton manager (Refer NielsenSdkManager.kt from the sample app source) and initializing the Android AppSDK when the app starts.

private var mAppSdk: AppSdk? = null

fun initializeAppSdk(context: Context, config: JSONObject) {
    mAppSdk = AppSdk(context, config, object : IAppNotifier {
        override fun onAppSdkEvent(timestamp: Long, code: Int, description: String?) {
            if (code == AppSdk.EVENT_STARTUP) {
                Log.d("Nielsen", "AppSdk initialized successfully")
            }
        }
    })
    
    if (mAppSdk?.isValid != true) {
        Log.e("Nielsen", "Failed to initialize AppSdk")
    }
}

Step 4: Starting the AppSDK Measurement (DCR/DTVR)

4.1: The following example code demonstrates the invocation of play() and loadMetadata() api calls whenever video playback begins.

fun appStartMeteringVideo(video: Video) {
    // Build content metadata
    val metaData = JSONObject()
        .put("type", "content")               // type of content [required]
        .put("assetid", "uniqueassetid")      // unique ID for each asset [required]
        .put("program", "Program Name")       // name of program [required]
        .put("title", "Episode Title")        // name of the episode [required]
        .put("length", "3600")                // length of content [required]
        .put("adloadtype", "2")               // type of ad load i.e 1=linear, 2=dynamic [required for DCR Video]
        .put("adModel", "2")                  // type of ad load i.e 1=linear, 2=dynamic [required for DTVR]
    
    // Build channel information
    val channelInfo = JSONObject()
        .put("channelName", "channelName")  // pass descriptive stream information through this parameter
        .put("mediaURL", "videoUrl")        // Video URL value for the content that is being played
    
    // Start measurement
    mAppSdk?.play(channelInfo)
    mAppSdk?.loadMetadata(metaData)
}


A comprehensive list of parameters which can be passed to AppSDK are listed here - play() and loadMetadata()


4.2: The following example demonstrates the passing of playhead positions to AppSDK every one second during the playback of content. This is needed for DCR Video measurement.

fun monitorPlayhead(exoPlayer: ExoPlayer) {
    monitorJob = lifecycle.coroutineScope.launch(Dispatchers.Main) {
      var ticks = 0
        while (isActive) {
            if (exoPlayer.isPlaying) {
                val positionMs = exoPlayer.currentPosition
                val durationMs = exoPlayer.duration
                
                ticks++
               // Report every 1 second (since loop runs every 500ms)
                if (ticks % 2 == 0) {
                val playheadToReport: Long = if (videoDuration <= 0) {
                     System.currentTimeMillis() / 1000  // Live: UTC time
                  } else {
                     videoPosition.toLong()  // VOD: Position from start
                   }
              
                mAppSdk?.setPlayheadPosition(playheadSeconds)
            }
            delay(500)
        }
    }
}


4.3: The following example demonstrates the passing of Nielsen ID3 tags to AppSDK during the playback of content. This is needed for DTVR measurement.

The following example code demonstrates the extraction of ID3 metadata events from ExoPlayer.

inner class PlayerEventListener : Player.Listener {
    override fun onMetadata(metadata: Metadata) {
        for (i in 0 until metadata.length()) {
            val entry = metadata.get(i)
            if (entry is PrivFrame) {
                val owner = entry.owner
                val data = String(entry.privateData, Charsets.UTF_8)
                
                // Check if it's a Nielsen ID3 tag
                if (owner.contains("nielsen", ignoreCase = true) ||
                    owner.contains("www.nielsen.com", ignoreCase = true)) {
                    appProcessID3tag(owner + data)
                }
            }
        }
    }
}
fun appProcessID3tag(id3String: String?) {
    try {
        mAppSdk?.sendID3(id3String)
    } catch (e: Exception) {
        Log.e("Nielsen", "Cannot process ID3 tag: ${e.message}")
    }
}

Step 5: Stopping the AppSDK Measurement (DCR/DTVR)

The following code snippet demonstrates the pausing of AppSDK measurement whenever the video playback is paused or when switching between ad to content or content to ad.

fun appStopMeteringVideo() {
    mAppSdk?.stop()
}


The following code snipped demonstrates the completion of AppSDK measurement in case of DCR Video typically used when content playback is completed. This is triggered 1) at the end of the content stream 2) if the user switches to another piece of content

Note: In case of DTVR this acts as an interrupt similar to stop() api

fun appEndMeteringVideo() {
    mAppSdk?.end()
}

Step 6: Measuring Non Video Content (DCR Static)

The following code snippet demonstrates the measurement of static screens/pages by sending the metadata of the static page/screen to AppSDK.

fun staticLoadMetadata() {
    val metadata = JSONObject()
        .put("type", "static")                    // type of content [required]
        .put("section", "Web View Screen")        // section of site [required]
        .put("segA", "CustomSegmentA")            // custom segment [optional]
        .put("segB", "CustomSegmentB")            // custom segment [optional]
        .put("segC", "CustomSegmentC")            // custom segment [optional]
        .put("crossId1", "Standard Episode ID")   // [optional]
        .put("crossId2", "Content Originator")    // [optional]
    
    mAppSdk?.loadMetadata(metadata)
}


The following code snippet demonstrates the completion of static screens/pages measurement by invoking staticEnd() on AppSDK which will finalise the screen/page viewed time.

fun staticEnd() {
    mAppSdk?.staticEnd()
}

Step 7: Opting out of AppSDK measurement

The following example code is to provide users the ability to opt out of Nielsen measurement.

Below code snippet is used to fetch the Nielsen opt-out web page URL

fun getOptOutUrl(): String {
    return mAppSdk?.userOptOutURLString() ?: ""
}
// Load this URL in a WebView
webView.loadUrl(getOptOutUrl())


Below code snippet is used to supply the response message captured from opt-out webpage to the AppSDK

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        val url = request.url.toString()
        
        // Check for Nielsen opt-out response
        if (url.startsWith("nielsenappsdk://")) {
            mAppSdk?.userOptOut(url)
            // Navigate back or show confirmation
            return true
        }
        return false
    }
}

Step 8: Closing the AppSDK instance

Kindly call this API whenever the application is closing or before creating another AppSDK instance.

fun appCloseMeteringVideo() {
    mAppSdk?.close()
    mAppSdk = null
}

Quick Reference - Android AppSDK Methods

The table below provides a summary of the core Android AppSDK methods, their primary functions, and the appropriate triggers for calling them within your application lifecycle.

Method Purpose When to Call
play(channelInfo) Start content session Video playback begins.
loadMetadata(metadata) Send content/Ad/static info After play API call or for static content.
setPlayheadPosition(video playback pos) Report playhead position setPlayheadPosition(pos) - sets the playhead position in AppSDK as video playback time (seconds) in the content (VOD Video On Demand) or the current UTC time for live stream.
sendID3(tag) Process DTVR videos When ID3 tag received from stream.
stop() Pause measurement Video paused.
end() End content session Video playback ends.
staticEnd() End static session Leave static content screen.
close() Destroy SDK instance App exit only.
userOptOutURLString() Get opt-out URL Display opt-out WebView.
userOptOut(url) Set opt-out preference When the user completes the opt-out.
getNielsenId() Retrieve Nielsen ID When need to access the unique Nielsen identifier.
getDeviceId() Retrieve Device ID When need to access the unique device identifier.
getDemographicId() Retrieve Demographic ID When need to access the AppSDK session identifier.
getMeterVersion() Retrieve SDK Meter Version When need to check the current SDK version.
getOptOutStatus() Retrieve the Opt-Out or Opt-In state. When need to know the Opt-Out or Opt-In status.

Sample App: Download, Build, Emulator Setup and Install the AndroidTV

The following section provides instructions for downloading the sample application, building the APK within Android Studio, and setting up the necessary Android TV emulator environment for testing.

1: Download the package here

Click here to  download the project and open the project in Android Studio IDE.

2: Build the APK from this Project

Before building the apk, create an AndroidTV emulator from the IDE and install the App directly through Android Studio.

Follow the steps to test AndroidTV sample Apps in TV Emulators and how to build the app from the client package.

3: Create the Android TV Emulator

To create an Android TV emulator, you primarily use Android Studio to set up an Android Virtual Device (AVD).

4: Install the AndroidTV sample video player App

Once you have built the APK and configured your Android TV emulator, use either of the following methods to install the sample video player application.

Method 1: Drag and Drop (Easiest)

Use your mouse to drag and drop the APK onto the running emulator :

  1. Launch the Android TV emulator.
  2. Locate the .apk file on your computer.
  3. Drag the file and drop it directly onto the emulator window.
  4. Wait for the installation to automatically complete.


Method 2: Use ADB (Command Line)

Use the Android Debug Bridge (ADB) if you have the Android SDK Platform-Tools installed :

  1. Open the terminal or command prompt.
  2. Ensure emulator is running and detected by typing: -> adb devices.
  3. Install the APK by running the following command: -> adb install path/to/your/sample_app.apk.

Open up Android TV Emulator

After installing the sample app, follow these steps to launch the Nielsen Sample TV application on your emulator.

Select Nielsen Sample TV App  -> Select Legacy Option

Screenshot 20260527 133449.png
Screenshot 20260527 133705.png
Screenshot 20260527 134418.png
Screenshot 20260529 152139.png

Setting page for  select  Opt out/in options

Screenshot 20260527 134647.png

Next Steps

If there are any questions or concerns then please reach out to the AppSDK team. Reference the following guides for product specific information :

For further technical details , please contact your Technical Account Manager (TAM).