Nielsen SDK

Android with Chromecast Implementation

last update: 24.6.2021



Sender App

Sender app is a native app (Android, iOS, Js) runs on a mobile device or laptop, controlled by end-user


Receiver App

Receiver app is an HTML5/JavaScript application placed at custom URL handles communication between the sender app and the ChromeCast device.


Cast Scenarios


Pure casting scenario

Pure casting scenario is when video was casted, any playing only at ChromeCast device.
Sender app should not pass any further Nielsen API calls once casting starts, all Nielsen API calls are handled by Reciever App.


Chromecast mirroring scenario

Pure casting scenario is when video was casted, any playing only at ChromeCast device.
Sender app should not pass any further Nielsen API calls once casting starts, all Nielsen API calls are handled by Reciever App.


Sender App (Android/Java)

Implement Nielsen AppSDK into your native application as ussual, see related implementation guide. Find below additional cast-specific API calls.


API call updateOTT

mAppSdk.updateOTT(JSONObject ottInfo)

Use updateOTT method to notify App SDK that the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected / disconnected (change of OTT status).
When OTT device is connected, call updateOTT with "ottStatus": "1" and a set of OTT device related parameters in ottInfo JSONObject.

                                                ottConfig = new JSONObject()
                                                .put("ottStatus", "1")
                                                .put("ottName", "casting”) // (casting, screen mirroring, ..) 
                                                .put("ottDevice", "chromecast")
                                                .put("ottDeviceName", "Google ChromeCast")
                                                .put("ottDeviceID", "xxxx-xxxx-xxxx")
                                                .put("ottDeviceManufacturer", "Google")
                                                .put("ottDeviceModel", "ChromeCast")
                                                .put("ottDeviceVersion", "1.0.0");
                                            

When OTT device is disconnected, call updateOTT with "ottStatus": "0" in ottInfo JSONObject.

                                                ottConfig = new JSONObject()
                                                .put("ottStatus", "0")
                                            
Notes :
  • Every time when application is launched or moving to foreground, call updateOTT to report the current OTT status to the App SDK.
  • The application needs to report all the possible OTT types (casting, screen mirroring, and any other types) to App SDK.
  • Some Variables of ottConfig object can be populated from Cast Framework as below
                                            String ottDeviceName = castSession.getCastDevice().getFriendlyName();
                                            String ottDeviceId = castSession.getCastDevice().getDeviceId();
                                            String ottDeviceModelName = castSession.getCastDevice().getModelName();
                                            String ottDeviceVersion = castSession.getCastDevice().getDeviceVersion();
                                            


API call getOptOutStatus() and getDemographicId()

                                                mAppSdk.getOptOutStatus()
                                                mAppSdk.getDemographicId()
                                            

The sender device will need to retrieve the Opt Out status using getOptOutStatus() and the Demographic ID using getDemographicId(). Sent the values only once to the Chromecast, at the beginning of the casting session. Run both API calls in AsyncTasks to retrieve prover values.

1. Define pre-defined static variables

                                                private static final String MEDIA_METADATA_KEY_DEVICE_ID = "kGCKMetadataNlsKeyDeviceID";
                                                private static final String MEDIA_METADATA_KEY_OPTOUT_STATE = "kGCKMetadataNlsKeyOptout”;
                                            

2. Start AsyncTask to retrieve values

                                if(mSdkDevIdAndOptoutStateFetcherThread != null && !mSdkDevIdAndOptoutStateFetcherThread.isAlive()){
                                mSdkDevIdAndOptoutStateFetcherThread.start();    
                                }
                                
                                 private class SdkDevIdAndOptoutStateFetcherThread extends Thread
                                    {
                                        @Override
                                        public void run()
                                        {
                                            if(mAppSdk != null)
                                            {
                                                // Get the demographic id and the user optout status from AppSDK
                                                mDemographicId = mAppSdk.getDemographicId();
                                                mSdkOptoutState = String.valueOf(mAppSdk.getOptOutStatus());
                                                runOnUiThread(new Runnable()
                                                {
                                                    @Override
                                                    public void run()
                                                    {
                                                        // Once the optout status is retrieved, proceed with the casting of media to remote cast device
                                                        onApplicationConnected(mCastSession);
                                                    }
                                              });}} }
                                            

3. Pass result of getOptOutStatus() and getDemographicId() to defined variable within MediaMetaData

MediaMetadata mediaMetadata = new MediaMetadata( MediaMetadata.MEDIA_TYPE_MOVIE );
mediaMetadata.putString( MediaMetadata.KEY_TITLE, channelName.getText().toString());

mediaMetadata.putString( MEDIA_METADATA_KEY_DEVICE_ID, mDemographicId);
mediaMetadata.putString( MEDIA_METADATA_KEY_OPTOUT_STATE, mSdkOptoutState);

MediaInfo mediaInfo = new MediaInfo.Builder(mNowPlayingUrl)
            .setContentType( getString( R.string.content_type_mp4 ) )
            .setStreamType( MediaInfo.STREAM_TYPE_BUFFERED )
            .setMetadata( mediaMetadata )
            .build();
                                            
Notes :
  • To get more information about Opt Out please refer to general AppSDK implementation guide Chapter Step 6: Privacy and Nielsen Opt-Out.
  • Result of getOptOutStatus() should be 0 or 1 (true or false),
  • Result of getDemographicId() is number (like example a5ff494cce22bda39b29da2509f90f52e4e044587107ba9ca092eb3a1c2eccdf)


Reciever app (JavaScript)

Once Casting starts, the Receiver side comes into picture, where one have to create BSDK instance and call its API events – see guide for Browser SDK (portal).


BSDK init

BSDK receiver instance gets initialized on load of chromecast receiver app.

                            window.nolSDKInstance = NOLBUNDLE.nlsQ("Pxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", "ChromeCastInstance" );
                        

Note: replace Pxx with your AppID provided by Nielsen.


LoadMetadata

On load of remote player, retrieve content metadata sent by sender and pass it using API call loadMetadata

                            var metadata = {
                                "assetid" : senderMetadata.assetid,
                                "type" : senderMetadata.type,
                                "program" : senderMetadata.program,
                                "title" : senderMetadata.title,
                                "length" : senderMetadata.length,
                                "mediaUrl" : senderMetadata.mediaUrl,
                                "airdate" : senderMetadata.airdate,
                                "isfullepisode" : senderMetadata.isfullepisode,
                                "crossId1" : senderMetadata.crossId1,
                                "nol_c1" : senderMetadata.nol_c1,
                                "nol_c2" : senderMetadata.nol_c2,
                                "segB" : senderMetadata.segB,
                                "segC" : senderMetadata.segC,
                                "adloadtype" : senderMetadata.adloadtype,
                                "hasAds" : senderMetadata.hasAds
                            };
                            window.nolSDKInstance.ggPM('loadmetadata', metadata);
                        

Note : refer to specification of Czech MetaData and follow it


updateOTT

Send updateOTT event to BSDK receiver instance. To relay the sender ottmetadata (kGCKMetadataNlsKeyDeviceID and kGCKMetadataNlsKeyOptout) received from sender app.

sessionId = senderMetadata.kGCKMetadataNlsKeyNUID?
senderMetadata.kGCKMetadataNlsKeyNUID:senderMetadata.kGCKMetadataNlsKeyDeviceID;

var contentMetadataObject ={
                        type: "content",
                        ottStatus: "1",
                        ottType: "casting",
                        ottDevice: "chromecast",
                        ottDeviceName: "Google Chromecast",
                        ottDeviceID: sessionId,
                        ottDeviceManufacturer: "Google",
                        ottDeviceModel: "ChromeCastModel",
                        ottDeviceVersion: "1.0.0",
    kGCKMetadataNlsKeyOptout : (["1",true,1,"true"].indexOf(senderMetadata.kGCKMetadataNlsKeyOptout)>=0)?true:false,
                        kGCKMetadataNlsKeyDeviceID : sessionId
                  };
window.nolSDKInstance.ggPM('updateOTT', contentMetadataObject);
                        


Rest of API calls

Fire all other API calls based on App/Player state. Refer to BSDK implementation guide.

// play
window.nolSDKInstance.ggPM('play',Math.round(event.path[0].currentTime));

// setPlayheadPosition
window.nolSDKInstance.ggPM('setPlayheadPosition',Math.round(event.path[0].currentTime));

// pause
window.nolSDKInstance.ggPM('pause',Math.round(event.path[0].currentTime));

// stop
window.nolSDKInstance.ggPM('stop',Math.round(event.path[0].currentTime));

// end
window.nolSDKInstance.ggPM('end',Math.round(event.path[0].currentTime));
                        


Sample code

Below is a sample code snippet on how the receiver app should retrieve the ottMetadata received from sender apps and relay the information to receiver BSDK instance.

                            sampleplayer.CastPlayer.prototype.onLoad_ = function(event) {

                                var senderMetadata = event.data.media.metadata,
                                
                                sessionId =senderMetadata.kGCKMetadataNlsKeyDeviceID;
                                
                                  this.cancelDeferredPlay_('new media is loaded');
                                  this.load(new cast.receiver.MediaManager.LoadInfo( (event.data),  event.senderId));
                                    var contentMetadata = {
                                              "assetid" : senderMetadata.assetid,
                                              "type" : senderMetadata.type,
                                              "program" : senderMetadata.program,
                                              "title" : senderMetadata.title,
                                              "length" : senderMetadata.length,
                                              "airdate" : senderMetadata.airdate,
                                              "isfullepisode" : senderMetadata.isfullepisode,
                                              "crossId1" : senderMetadata.crossId1,
                                              "nol_c1" : senderMetadata.nol_c1,
                                              "nol_c2" : senderMetadata.nol_c2,
                                              "segB" : senderMetadata.segB,
                                              "segC" : senderMetadata.segC,
                                              "adloadtype" : senderMetadata.adloadtype,
                                              "hasAds" : senderMetadata.hasAds
                                    };
                                
                                      window.nolSDKInstance.ggPM('loadmetadata', contentMetadata);
                                
                                       var ottMetadataObject ={
                                            ottStatus: "1",
                                            ottType: "casting",
                                            ottDevice: "chromecast",
                                            ottDeviceName: "Google Chromecast",
                                            ottDeviceID: sessionId,
                                            ottDeviceManufacturer: "Google",
                                            ottDeviceModel: "ChromeCastModel",
                                            ottDeviceVersion: "1.0.0",
                                            kGCKMetadataNlsKeyOptout : senderMetadata.kGCKMetadataNlsKeyOptout,
                                                      kGCKMetadataNlsKeyDeviceID : sessionId
                                          };
                                
                                window.nolSDKInstance.ggPM('updateOTT', ottMetadataObject);};
                        


Summary - Correct sequence of API calls

Find bellow API calls sequence from the beggining of Casting until its end.


Sender side

1) Video is playing only at Sender - Call all API call as in standard App with Nielsen SDK
2) Once user press Cast icon - If video was playing already - call end()
3) Inform AppSDK about ChromeCast status (connected / dissconected) - call updateOTT(config)
4) Retrieve optOutStatus and Demographic data - call getOptOutStatus() and call getDemographicId()
5) Pass it into MediaMetaData
6) Start Casting (video stoped at Sender)

Receiver side

Playback started at ChromeCast device (TV)
7) Retrieve MediaMedaData sent by Sender
8) Instantiate Browser SDK
9) Pass metadata - call loadMetaData()
10) Pass playheads every second - call setPlayheadPosition()
11) Based on user interaction or playlist state - call stop() (once paused) or end() (content ended or cast ended)

Sender side

Cast ended and playback continues at Sender
12) Start new session - call play() and call loadMetaData()
13) Continue API calls as usual


Testing implementation

See https://developers.google.com/cast/docs/debugging
Note : make sure that all your test devices and PC are connected in the same network segment.
1. Start Android application and play video
2. Connect app to ChromeCast pressing Cast button

3. Launch Chrome browser and access URL chrome://inspect
4. Under your ChromeCast device press “inspect”

5. In console – check JS activity including Nielsen SDK, Note : make sure that BSDK has DEBUG mode on

6. In Network – make sure that ourgoing data to Nielsen collection are present


Demos

See live demos with sample implementation available at http://sdkdemo.admosphere.cz/


Contacts

Company

Nielsen Admosphere

Českobratrská 2778/1

130 00 Praha 3

www.nielsen-admosphere.cz


Administration, testing, certification and technical support

Tomáš Kuchler

Technical Account Manager

+420 777 814 468

tomas.kuchler@admosphere.cz


NielsenSDK Team

SDKsupport@admosphere.cz