AndroidTV
From Engineering Client Portal
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 Video (Digital Content Ratings) for measuring VOD and live streaming video content by tracking playhead position 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 watermarks embedded in the broadcast signal.
Step 1: Android AppSDK Integrations into Android TV App
This steps covers the complete integration process including AppSDK initialization, content metadata configuration, playhead tracking, ID3 tag processing, and user opt-out/in implementation.
1.1: Add Nielsen AppSDK Dependency
Add the Nielsen Android AppSDK Jar maven dependency to the App module and configure build.gradle.
build.gradle (app level)
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"
}
1.2: Configure Android AppSDK Parameters
Build the JSON configuration with Nielsen credentials.
val config = JSONObject()
.put("appid", "NIELSEN_APP_ID") // Nielsen-provided App ID [required]
.put("sfcode", "cert") // cert for testing, [Optional]
.put("clientid", "client_id") // Client identifier [Optional]
.put("vcid", "vcid") // vendor client id [Optional]
.put("prod", "dcrvideo") // Product codes [Optional]
.put("category", "category") // App category [Optional]
.put("nol_devDebug", "DEBUG") // Remove in production
.put("uid2", "unified_id_value") // UID2 identifier [Optional]
.put("hem_sha256", "hashed_email") // Hashed email [Optional]
1.3: Initialize Android AppSDK
The following example code is for creating a singleton manager 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")
}
}
1.4: DCR Video - Start Measurement
The following example code is for Call play() and loadMetadata when 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") // ex: S1E3 [required]
.put("length", "3600") // length of content [required]
.put("category", "Entertainment") // content category [required]
.put("adModel", "2") // 1=linear, 2=dynamic [required]
// Build channel information
val channelInfo = JSONObject()
.put("channelName", "channelName")
.put("mediaURL", "videoUrl")
// Start measurement
mAppSdk?.play(channelInfo)
mAppSdk?.loadMetadata(metaData)
}
Reporting playhead position every 1 second during active playback.
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)
}
}
}
1.5: DCR Video - Stop/End Measurement
The following example code is for Signal playback state changes for accurate measurement.
Pause Playback :
fun appStopMeteringVideo() {
mAppSdk?.stop()
}
End Content Session (Video End) :
fun appEndMeteringVideo() {
mAppSdk?.end()
}
Close SDK (App Exit Only) :
fun appCloseMeteringVideo() {
mAppSdk?.close()
mAppSdk = null
}
1.6: DCR Static - Web Content Measurement
The following example code is for measuring non-video content like WebViews and articles.
Start Static Measurement :
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)
}
End Static Measurement :
fun staticEnd() {
mAppSdk?.staticEnd()
}
1.7: DTVR - ID3 Tag Processing
The following example code is for processing Nielsen ID3 watermarks from live TV streams for DTVR measurement.
Listen for ID3 Metadata (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)
}
}
}
}
}
Send ID3 Tag to Nielsen SDK :
fun appProcessID3tag(id3String: String?) {
try {
mAppSdk?.sendID3(id3String)
} catch (e: Exception) {
Log.e("Nielsen", "Cannot process ID3 tag: ${e.message}")
}
}
1.8: User Opt-Out Implementation
The following example code is to provide users the ability to opt out of Nielsen measurement via WebView.
Get Opt-Out URL :
fun getOptOutUrl(): String {
return mAppSdk?.userOptOutURLString() ?: ""
}
// Load this URL in a WebView
webView.loadUrl(getOptOutUrl())
Handle Opt-Out Response :
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
}
}
Check Opt-Out Status :
fun getOptOutStatus(): Boolean {
return mAppSdk?.optOutStatus ?: false
}
1.9: Android AppSDK Getter Methods
These methods provide information like Android AppSDK Version, NielsenId details.
Get Nielsen ID :
fun getNielsenId(): String = mAppSdk?.nielsenId ?: ""
Get Device ID :
fun getDeviceId(): String = mAppSdk?.deviceId ?: ""
Get Demographic ID :
fun getDemographicId(): String = mAppSdk?.demographicId ?: ""
Get SDK Meter Version :
fun getMeterVersion(): String = AppSdk.getMeterVersion()
Step 2: 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. |
Step 3: Sample App: Download, Build, and Emulator Setup
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.
3.1: Download the package here
Click here to download the project and open the project in Android Studio IDE.
3.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.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).
Step 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 :
- Launch the Android TV emulator.
- Locate the .apk file on your computer.
- Drag the file and drop it directly onto the emulator window.
- 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 :
- Open the terminal or command prompt.
- Ensure emulator is running and detected by typing: -> adb devices.
- Install the APK by running the following command: -> adb install path/to/your/sample_app.apk.
Step 5: 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
Setting page for Select Opt out/in options
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).