DCR Static Android SDK

From Engineering Client Portal

Engineering Portal / Digital / US DCR & DTVR / DCR Static Android SDK

Overview

This guide covers DCR Static Only Implementation information for the Nielsen SDK. If implementation measurement for Video, please refer to our Video Guide.

Prerequisites

Before you start the integration, you will need:

Item Description Source
App ID (appid) Unique ID assigned to the player/site and configured by product. Provided by Nielsen
Nielsen SDK Includes SDK frameworks and sample implementation; See Android SDK Release Notes Download

If need App ID(s) or our SDKs, feel free to reach out to us and we will be happy to help you get started. Refer to Digital Measurement Onboarding guide for information on how to get a Nielsen App SDK and appid.

Implementation

This guide covers implementation steps for Android Studio utilizing the Nielsen SDK for DCR.

SDK Flavor Description
Android Ad Version * Opt-In and Opt-Out functionality managed by Opt out of Ads Personlization setting on device. (Preferred approach)
* The Nielsen SDK will collect the Google Advertising ID unless the user Opts Out.
* If the Google Play Service is unavailable, (ie: Amazon and Huawei devices) the Nielsen sdk will secure the Android ID.
* There are 3 versions available starting with the Nielsen SDK 8.1.0.0.
Android No Ad Framework * Without the Ad Framework, the Nielsen SDK cannot read the Google Advertising ID, so will retrieve the AndroidID.
* The AndroidID is a 64-bit number (expressed as a hexadecimal string), unique to each combination of app-signing key, user and device.
* The developer is required to present the User Choice Opt Out page which is described in the Privacy Section.
Android SDK noID * This version of the Nielsen SDK is perfect for Kid apps, or where no ID is required.
* Please review the Opt Out Requirement.

How to obtain the NielsenAppApi

The Nielsen AppSDK can either be downloaded directly or can be integrated directly within an application through the use of Gradle. We recommend using the Gradle-based integration whenever possible to ensure you maintain the most recent changes and enhancements to the Nielsen libraries.

SDK Initialization

The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)

The following table contains the list of arguments that can be passed via the AppInfo JSON schema.

Parameter / Argument Description Source Required? Example
appid Unique Nielsen ID for the application. The ID is a GUID data type. If you did not receive your App ID, let us know and we will provide you. Nielsen-specified Yes PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
nol_devDebug Enables Nielsen console logging. Only required for testing Nielsen-specified Optional "DEBUG"

Debug flag for development environment

Player application developers / integrators can use Debug flag to check whether an App SDK API call made is successful. To activate the Debug flag, Pass the argument @"nol_devDebug":@"INFO", in the JSON string . The permitted values are:

  • INFO: Displays the API calls and the input data from the application (validate player name, app ID, etc.). It can be used as certification Aid.
  • WARN: Indicates potential integration / configuration errors or SDK issues.
  • ERROR: Indicates important integration errors or non-recoverable SDK issues.
  • DEBUG: Debug logs, used by the developers to debug more complex issues.

Once the flag is active, it logs each API call made and the data passed. The log created by this flag is minimal.

Note: DO NOT activate the Debug flag in a production environment.

Sample SDK Initialization Code

AppSDK() is no longer a singleton object and should be initialized as below.

Initialization of App SDK object through a JSON object

try
{
  // Prepare AppSdk configuration object (JSONObject)
  JSONObject appSdkConfig = new JSONObject()
          .put("appid", "PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA")
          .put("nol_devDebug", "DEBUG"); // only for debug builds

// Pass appSdkConfig to the AppSdk constructor
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);
}
catch (JSONException e)
{
  Log.e(TAG, "Couldn’t prepare JSONObject for appSdkConfig", e);
}

Here, appContext is the App context object and appSdkConfig is JSON object for holding the parameters (appid) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.


The integration of Nielsen App SDK will depend on type of client app.

  • Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).

Configure API calls - play

For static <App Measurement> content, play API is not required.

Configure API calls - loadMetadata

Use loadMetadata to pass 'content' Digital Measurement Metadata. The CMS data must be passed as a JSON object.

    loadMetadata(JSONObject jsonMetadata);

Refer to Digital Measurement Metadata for the list of parameters to be passed in the JSON object.

Note: The loadMetadata call must have ("type": "static").

Configure API calls - playheadPosition

For static <App Measurement> content, no playhead has to be supplied to the SDK.

stop

For static <App Measurement> content, stop API is not required.

API Call sequence

Call loadMetadata with JSON metadata as below.

    new JSONObject()
        .put("type", "static")
        .put("section", "siteSection")
        .put("assetid", "vid345-67483")
        .put("segA", "segmentA")
        .put("segB", "segmentB")
        .put("segC","segmentC")
    }

Sdk dataflow.jpg

Configure Metadata

Map the Nielsen keys to variables so that the content metadata is dynamically updated.

The Nielsen reserved keys are:

Key Description Data Type Value Required?
type asset type fixed 'static' Yes
assetid Unique ID for each article dynamic custom
(no Special Characters)
No
section section of each site (e.g. section value should be first level in page URL: website.com/section). Limit to 25 unique values dynamic custom Yes
segA custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No
segB custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No
segC custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No

The values passed through the Nielsen keys will determine the breakouts that are seen in reporting. The custom segments (A, B & C) will roll into the sub-brand. To not use custom segments A, B and C, do not pass any value in these keys.

Aggregation Limits There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:

Key Aggregation Limit
section maximum of 25 unique values (section <= 25)
segA Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
segB Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
segC Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)

DCR Static Duration Measurement per Section/Page/Asset

If your Nielsen AppID is enabled for DCR Static duration measurement, a view event will be recorded and a timer will be started for each screen/page. Duration will be measured until a new page is loaded or the app is moved to the background. The event which triggers recognition of page view and timer start is the loadMetadata API call with a metadata object of type 'static'. Once a page is viewed and the timer has started, duration will be measured until a new page has loaded with associated loadMetadata call having a different section name from the previous page. If a new loadMetadata call is made with the same section name, it will be ignored - no new view will be recorded. If it is desired to have a new view event even though the metadata contains the same section name (example: single-page apps having several assedIDs but common section name), staticEnd API can be called between page views.
Show flow diagram for above description

DCRstaticflow.png


Example 1 - In this example, a static view and duration ping with duration=25 will be generated for "SPORTS" section.
Show Android Java Example

JSONObject staticMetadataSports = new JSONObject();
staticMetadataSports.put("type","static");
staticMetadataSports.put("section","SPORTS");
nielsenSDK.loadMetadata(staticMetadataSports);
        
      //in this example, after 25 seconds, new metadata is loaded for section "MOVIES"                   

JSONObject staticMetadataMovies = new JSONObject();
staticMetadataSports.put("type","static");
staticMetadataSports.put("section","MOVIES");
nielsenSDK.loadMetadata(staticMetadataMovies);


Example 2 - In this example,, let's assume 20 seconds after the page is viewed, the app goes to background. A static duration ping with duration=20 will be generated for "SPORTS" section.
Show Android Java Example

JSONObject staticMetadataSports = new JSONObject();
staticMetadataSports.put("type","static");
staticMetadataSports.put("section","SPORTS");
nielsenSDK.loadMetadata(staticMetadataSports);        
  
  //App goes to background or killed after 20 seconds.

Note: Once the app is returned to foreground or relaunched, the app needs to pass static metadata again in order to restart measuring DCR Static duration.

Example 3 - Here we wish to generate a new view event and start a new duration timer even though the section name in the metadata is the same.
Show Android Java Example

JSONObject staticMetadataSports = new JSONObject();
staticMetadataSports.put("type","static");
staticMetadataSports.put("section","SPORTS");
staticMetadataSports.put("assetid","TENNIS");
nielsenSDK.loadMetadata(staticMetadataSports); 
//in this example, after 25 seconds, we pass staticEnd before new metadata is loaded for section "SPORTS", but assetid "CRICKET"


nielsenSDK.staticEnd();

JSONObject staticMetadataSports = new JSONObject();
staticMetadataSports.put("type","static");
staticMetadataSports.put("section","SPORTS");
staticMetadataSports.put("assetid","CRICKET");
nielsenSDK.loadMetadata(staticMetadataSports);

Note: Even though the assetid has changed, a new view event would not be recognized unless staticEnd() is called in between loadMetadata calls, because the section name did not change.

Handling Foreground and Background states

There are a few approaches to managing the Foreground and Background states of an app available to use for state measurement.

  • Utilizing the Androidx LifeCycleObserver (The recommended approach starting sdk version 7.1.0.0+)
  • Utilizing the SdkBgFgDetectionUtility class
  • Adding a tag to the Manifest XML
  • Manual Management

The LifeCycleObserver

AndroidX replaces the original support library APIs with packages in the androidx namespace, and Android Studio 3.2 and higher provides an automated migration tool. (Select Refactor> Migrate to AndroidX from the menu bar.)

Starting with version 7.1.0, with AndroidX support, an additional utility is provided in the AppSDK - application background/foreground state detection by the AppSdk leveraging the Android Architecture component "LifeCycleObserver".

The AppSdk is now capable of detecting the application UI visibility state transitions between background and foreground, without forcing the applications to register for AppSdk's AppSdkApplication class, which is responsible for handling the detection of application background/foreground state transitions at present.

Please note, that if you already have an app designed that utilizes the depreciated SdkBgFgDetectionUtility Class, the AppSDK will ignore any calls to these methods if it can utilize the LifeCycleObserver. LifeCycleObserver based auto detection will take precedence.

Adding the AndroidX dependency

In order to make use of the app background/foreground state transition auto detection feature of AndroidX AppSdk, the app gradle file needs the androidx dependency. The AppSdk API calls - appInForeground() and appInBackground() will still be respected by AppSdk by executing the old AppSdk flow of handling "app in foreground" and "app in background" states as is.

Using the LifeCycle Extension

The following androidx dependency is required in the app gradle file:

implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"

If you would like to take advantage of this auto detection feature of AppSdk at the very initial stage (e.g. splash screen or at of app launch time), before the AppSdk is initialized, can do so by calling the following newly introduced AppSdk public api, passing the application context :

public static void registerLifeCycleObserver(Context applicationContext)

Log messages for the new auto detection

When the AppSdk app successfully registers for the LifeCycleObserver : Registered LifeCycleObserver for App Background/Foreground auto-detection

  • When the app enters the foreground state :App is in foreground, auto detected by AppSDK
  • When the app enters the background state :App is in background, auto detected by AppSDK
  • If the client app doesn't have the "androidx" gradle dependency and AppSdk fails to register LifeCycleObserver :AndroidX LifecycleObserver can not be observed. Please use androidx dependency to activate SDK auto-detection of app background/foreground state.
  • When the appInForeground() is explicitly called while LifeCycleObserver auto detection is active :Ignoring the appInBackground() call, as the App Background/Foreground auto-detection is active. The current state is - foreground
  • When the appInBackground() is explicitly called while LifeCycleObserver auto detection is active :Ignoring the appInBackground() call, as the App Background/Foreground auto-detection is active. The current state is - background

The SdkBgFgDetectionUtility class

Foreground/Background state measurement is a requirement of Nielsen AppSDK implementation which is especially crucial for static measurement. It may be implemented in multiple ways for Android. This includes

  • Enable the Nielsen SDK to measure background/foreground state by makingthe relevant update to the AndroidManifest.
  • Integrate Nielsen’s SdkBgFgDetectionUtility class within your Custom Application Class.
  • Custom implementation of the required methods within your application.

ForeGround/Background Measurement via AndroidManifest

The simplest way to measure the app background/foreground state is to add the following application tag to the Manifest XML. Integrating this into the Manifest XML will enable the SDK to measure app state directly. This approach is supported for Android 4.0 and up only; it requires that the application class is not in use for some other purpose.

<application android:name="com.nielsen.app.sdk.AppSdkApplication">

Using the Android SdkBgFbDetectionUtility Class

For developers who are already using the application class, it is recommended that background/foreground state is implemented using the SdkBgFgDetectionUtility class. The SdkBgFgDetectionUtility class is compatible with Android 4+ and has been made available to Nielsen clients. (You will need to copy/paste the code provided into a file).

Manual Background/ForeGround State Management

In cases where the developer is not able to use the AndroidManifest.xml solution nor the Nielsen provided SdkBgFgDetectionUtility class the developer will need to manually identify the change of state through the application and call the respective API (appInForeground() or appInBackground()) to inform the SDK regarding the change of state from background to foreground or foreground to background.

The SDK is informed about app state using the below methods.

AppLaunchMeasurementManager.appInForeground(getApplicationContext());
AppLaunchMeasurementManager.appInBackground(getApplicationContext());

Within the lifecycle of individual activities, onResume() and onPause() are best suited to providing indication of the app state.


Correct measurement of the foreground/background state is crucial to Static App measurement within Nielsen Digital Content Ratings (DCR).

Privacy and Opt-Out

There are currently 3 flavors of the Nielsen SDK:

  1. Global Android SDK Opt-out - managed by Opt out of Ads Personalization setting on device (preferred approach).
  2. Global Android SDK No Ad Framework Optout - Direct call to SDK. Can be used without Google Play Services or when using the noAd version of the SDK.
  3. Global Android SDK No ID Optout - Direct call to SDK. Should be used for Kids Category.

Global Android SDK Opt-out

OS-level Opt-out method available on Nielsen Android when the Google Play services APIs have been setup in your project.

The Nielsen SDK automatically leverages the Android's Opt out of Ads Personalization setting. The user is opted out of demographic measurement if the OS-level Opt out of Ads Personalization setting is enabled. As a publisher, you cannot override this setting.

Webview Element

It is a requirement to display a WebView element whose loadUrl is set to the value obtained from optOutURL. If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.

If you are implementing on Android TV or Fire TV here are your Opt Out verbiage options : https://engineeringportal.nielsen.com/docs/DCR_Video_%26_Static_CTV_Device_SDK_Privacy

Retrieve current Opt-Out preference

Whether the user is opted out via OS-level Opt-out or via App-level Opt-out, the current Opt-Out status as detected by the SDK is available via the getOptOutStatus() property in the Nielsen Android SDK API. appSdk.getOptOutStatus()

Global Android SDK No Ad Framework Optout

The No Ad Framework Optout can be used when the host application does not leverage Google Play Services such as when using the noAd version or the NoID version.

Nielsen Android SDK 5.1.1.18 and above will check for OS-level opt-out first, if available. The user will be opted out if indicated at the OS-level OR the App-level.

The No Ad Framework Optout method works as follows:

  • Get the current Nielsen opt-out URL via userOptOutURLString()
  • Display a WebView element whose loadUrl is set to the value obtained from userOptOutURLString()
  • Detect if the WebView URL changes to a special URL that indicates Opt-in, or Opt-out and close the WebView
    • Opt-out if the WebView URL = nielsenappsdk://1
    • Opt-in if the WebView URL = nielsenappsdk://0
  • Pass the detected URL to the userOptOut() function
    • Example:
      appSdk.userOptOut("nielsenappsdk://1");  // User opt-out
      

Global Android SDK No ID Optout (Kids_Category)

If you are building an app that will be listed in the Kids Category:

  1. Ensure that you are using the NoID version of the Nielsen SDK Framework.
  2. Immediately following the initialization of the Nielsen SDK ensure you call the userOptOut API with Opt out selection:
appSdk.userOptOut("nielsenappsdk://1");  // User opt-out

OptOut Example Code

Below you will find some sample code for the:

  • Global Android SDK - managed by Opt out of Ads Personalization setting on device (preferred approach).
  • Global Android noAd Framework - Use if Google Play APIs are unavailable or running noAd version.
  • It is currently not required to display an OptOut page for the NoID/Kids Build of the SDK.

Global OptOut Example

The below code is an AndroidX example of displaying the Nielsen Privacy page to the user. Please see the next section if using the No Ad Framework build

public class OptOutActivity extends AppCompatActivity implements IAppNotifier {

    WebView webView;
    AppSdk appSdk;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_optout);
        webView = (WebView) findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() {
            @SuppressWarnings("deprecation")
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                Toast.makeText(OptOutActivity.this, description, Toast.LENGTH_SHORT).show();
            }
            @TargetApi(android.os.Build.VERSION_CODES.M)
            @Override
            public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
                // Redirect to deprecated method, so you can use it in all SDK versions
                onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
            }

        });
        String url = appSdk.userOptOutURLString();   // Request Optout URL from NielsenSDK
        webView.loadUrl(url);                         //Display to the user in a Webview
    }
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        mSdkInterface.getSDK(appSdk);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (appSdk != null)
        {
            appSdk.close();
            appSdk = null;
        }
    }
}


No Ad Framework Optout Sample Code

The below code is an AndroidX example of displaying the Nielsen Privacy page to the user with the No Ad Framework SDK Build.

public class OptOutActivity extends AppCompatActivity implements IAppNotifier {

    WebView webView;
    AppSdk appSdk;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_optout);
        webView = (WebView) findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);

        webView.setWebViewClient(new WebViewClient() {
            @SuppressWarnings("deprecation")
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
                Toast.makeText(OptOutActivity.this, description, Toast.LENGTH_SHORT).show();
            }
            @TargetApi(android.os.Build.VERSION_CODES.M)
            @Override
            public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
                // Redirect to deprecated method, so you can use it in all SDK versions
                onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
            }

  
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {

                if(url.contains("nielsen")){
                    // If url value = "nielsenappsdk://1 it means the user selected Opt Out
                    // If url value = "nielsenappsdk://0" it means the user selected Opt-In
                    appSdk.userOptOut(url);
                }
                return true;
            }

        });
        String url = appSdk.userOptOutURLString();   // Request Optout URL from NielsenSDK
        webView.loadUrl(url);                         //Display to the user in a Webview
    }
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        mSdkInterface.getSDK(appSdk);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (appSdk != null)
        {
            appSdk.close();
            appSdk = null;
        }
    }
}

Retrieve current Opt-Out preference

Whether the user is opted out via OS-level Opt-out or via App-level Opt-out, the current Opt-Out status as detected by the SDK is available via the getOptOutStatus() property in the Nielsen Android SDK API. appSdk.getOptOutStatus()

Going Live

Following Nielsen testing, you will need to:

  1. Disable Debug Logging: Disable logging by deleting {nol_devDebug: 'DEBUG'} from initialization call.
  2. Notify Nielsen: Once you are ready to go live, let us know so we can enable you for reporting. We will not be able to collect or report data prior to receiving notification from you.

Pre-Certification Checklists

After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.

Testing an Implementation - App

See Digital Measurement Testing.