DCR Chromecast Android SDK

From Engineering Client Portal

Revision as of 20:57, 11 June 2019 by ColinBrown (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Engineering Portal breadcrumbArrow.png Digital breadcrumbArrow.png DCR & DTVR breadcrumbArrow.png DCR Chromecast Android SDK

1. General Cast architecture


Screen Shot 2018-09-25 at 10.26.22(1).png

See https://developers.google.com/cast/docs/developers

Sender App

is a user-controlled native app that runs on a mobile device (Android, iOS) or a laptop (JS).

Reciever App

is an HTML5/JavaScript application placed at a custom URL that handles communication between the sender app and the Chromecast device.

2. Cast scenarios

2.1 Pure casting scenario

The video is only playing on a Chromecast device.
The sender app should not pass any Nielsen API calls once the pure casting scenario starts. All Nielsen API calls are handled by the receiver app.

Screen Shot 2018-09-25 at 09.35.08.png

2.2 Chromecast mirroring scenario

The video is playing on both the sender and receiver apps.
Both the sender and receiver apps should pass Nielsen API calls.

Screen Shot 2018-09-25 at 09.35.19.png

3.Sender App (Android/Java) - Nielsen SDK implementation

3.1 General

By adding the below cast-specific API calls alongside the standard implementation of the Nielsen AppSDK into your native application, a sender app can pass appropriate cast-specific metadata.

3.2 API call updateOTT


mAppSdk.updateOTT(JSONObject ottInfo)


Use the updateOTT method to notify the AppSDK whether the remote OTT device (like Google ChromeCast, Roku, Amazon FireTV, etc.) is connected or disconnected (indicated by "ottStatus").

When the OTT device is connected, call updateOTT with "ottStatus": "1" as well as a set of OTT device related parameters in the ottConfig 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 the OTT device is disconnected, call updateOTT with "ottStatus": "0".

ottConfig = new JSONObject()
        .put("ottStatus", "0")

Notes:

  • Every time the application is launched or moves to foreground, call updateOTT to report the current OTT status.
  • The application needs to report all the possible OTT types (casting, screen mirroring, and any other types) to App SDK.
  • Some variables of the ottConfig object can be populated from the cast framework as seen below:
String ottDeviceName = castSession.getCastDevice().getFriendlyName();
String ottDeviceId = castSession.getCastDevice().getDeviceId();
String ottDeviceModelName = castSession.getCastDevice().getModelName();
String ottDeviceVersion = castSession.getCastDevice().getDeviceVersion();

3.3 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(). These values should be sent to the Chromecast at the beginning of the casting session. Both API calls must be run in AsyncTasks to retrieve proper 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 an alphanumeric string (ex: a5ff494cce22bda39b29da2509f90f52e4e044587107ba9ca092eb3a1c2eccdf)

4. Reciever app (JavaScript) - Nielsen SDK implementation

Once casting starts, the receiver app becomes important as a BSDK instance must be created and the related appropriate API events must be called. Please refer to the Browser SDK guide for more information.

4.1 BSDK init

The BSDK receiver instance gets initialized on load of the Chromecast receiver app.

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

Note: replace "Pxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx" with your Nielsen provided AppID.

4.2 LoadMetadata

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

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

4.3 updateOTT

Send the updateOTT event to BSDK receiver instance. The updateOTT event should relay the 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);

4.4 Rest of API calls

Fire off other API calls based on App/Player state. Refer to the BSDK implementation guide for more information.

// 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));

4.4 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,
              "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', 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);};

5. Summary - Correct squence of API calls

Below is the sequence of API calls sequence from the beginning to the end of casting.

SENDER side :

1) If the video is playing only on the sender app, the standard Nielsen SDK API calls should be invoked.
2) Once a user presses the cast icon and if the video was playing already, call end().
3) Inform the AppSDK about the Chromecast's status (connected or disconnected) by calling updateOTT(config metadata).
4) Retrieve the optOutStatus and demographicId by calling getOptOutStatus() and getDemographicId().
5) Pass the optOutStatus and demographicId into the MediaMetaData object.
6) Start casting (the video should be stopped on the sender device).

RECIEVER side :

Playback has started at ChromeCast device (TV)
7) Retrieve the MediaMedaData sent by the sender device.
8) Instantiate the Browser SDK.
9) Pass metadata by calling loadMetaData().
10) Pass playheads every second by calling setPlayheadPosition().
11) Based on the user's interactions or the playlist state, call stop() (once paused) or end() (once the content or casting has ended).

SENDER side :

Casting has ended and playback continues on the sender device
12) Start a new session by calling play() and loadMetaData().
13) Continue sending API calls as usual.

6. Testing implementation

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

Screen Shot 2018-09-25 at 10.15.38.png

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

Screen Shot 2018-09-25 at 10.15.49.png

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

Screen Shot 2018-09-25 at 10.16.02.png

6. In your Network – make sure that outgoing data to Nielsen collection is present.

Screen Shot 2018-09-25 at 10.21.23.png