DCR Chromecast Android SDK
From Engineering Client Portal
1. General Cast architecture
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).
Receiver 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.
2.2 Chromecast mirroring scenario
The video is playing on both the sender and receiver apps.
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. Receiver 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 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).
RECEIVER 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.
3. Launch Chrome browser and access URL chrome://inspect.
4. Under your ChromeCast device, press “inspect”
5. In your browser console, check JS activity - including Nielsen SDK. Note: make sure that the BSDK has DEBUG mode on.
6. In your Network – make sure that outgoing data to Nielsen collection is present.