Skip to main content

Chromecast

Chromecast on Quickplay platform qualifies as a device on its own and can perform device registration, content authorization and playback similar to any other conventional devices. The client sender facilitates sharing required information for device registration and content authorization to the receiver and the receiver processes the same for playback.

Cast Initialization

Application should complete this setup and setup theme for entire google cast session.

iOS Implementation

To integrate internal quick play casting, we need to explicitly include a patch file that contains the changes in the rn-qp-nxg-player.podspec, ensuring that default_subspecs includes both 'Release' and 'Casting'.

s.default_subspecs = 'Release', 'Casting'

The reason for this change is that Casting is a subspec that cannot be directly added to the React Native application's Podfile due to limitations with the react_native_pods module.

NOTE:
If internal quickplay casting integration is not required, avoid using its APIs, as doing so may result in warnings. Possible unhandled promise rejection(id: 1).

NOTE:
Internal quickplay casting is not integrated also you may encounter warnings for Casting APIs during app launch. Possible unhandled promise rejection(id: 1).

Next step to integrate the code change in appDelegate.swift file

NSString *receiverAppID = [RNCConfig envFor:@"CHROMECAST_APP_ID"];
GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:receiverAppID];
GCKCastOptions* options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria];
[GCKCastContext setSharedInstanceWithOptions:options];
options.physicalVolumeButtonsWillControlDeviceVolume = YES;
[GCKCastContext sharedInstance].useDefaultExpandedMediaControls = YES;

//Cast Dialogs UI Customization
GCKUIStyle *castStyle = [GCKUIStyle sharedInstance];
castStyle.castViews.backgroundColor = [UIColor colorWithRed: 0.07 green: 0.07 blue: 0.07 alpha: 1.00];
castStyle.castViews.headingTextColor = [UIColor whiteColor];
castStyle.castViews.headingTextFont = [UIFont fontWithName:@"Mulish-SemiBold" size:24.0];
castStyle.castViews.bodyTextColor = [UIColor whiteColor];
castStyle.castViews.bodyTextFont = [UIFont fontWithName:@"Mulish-Regular" size:14.0];
castStyle.castViews.iconTintColor = [UIColor whiteColor];
castStyle.castViews.buttonTextFont = [UIFont fontWithName:@"Mulish-SemiBold" size:14.0];
[castStyle applyStyle];

Note: Setting GCKCastContext instance should be done via main thread only.

For more details: https://developers.google.com/cast/docs/ios_sender/integrate#initialize_the_cast_context

Android Implementation

Integrate the code change in androidManifest.xml file

<activity android:name=".views.CastControlActivity" android:screenOrientation="portrait" android:exported="true" android:theme="@style/SplashTheme"/>
<activity
android:name=".views.ExpandedControlsActivity"
android:launchMode="singleTask"
android:theme="@style/SplashTheme"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:value="com.univision.univisionnow.CastOptionsProvider"/>
import com.univision.univisionnow.views.ExpandedControlsActivity
import android.content.Context
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.SessionProvider
import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.MediaIntentReceiver;
import com.google.android.gms.cast.framework.media.NotificationOptions

class CastOptionsProvider : OptionsProvider {
private val TAG = "CastOptionsProvider"

override fun getCastOptions(context: Context): CastOptions {
val buttonActions: MutableList<String> = ArrayList()
buttonActions.add(MediaIntentReceiver.ACTION_REWIND)
buttonActions.add(MediaIntentReceiver.ACTION_TOGGLE_PLAYBACK)
buttonActions.add(MediaIntentReceiver.ACTION_FORWARD)
buttonActions.add(MediaIntentReceiver.ACTION_STOP_CASTING)

val compatButtonActionsIndices = intArrayOf(1, 3)

// Tapping on the notification opens an ExpandedControllerActivity with class ExpandedControlsActivity.
val notificationOptions = NotificationOptions.Builder()
.setActions(buttonActions, compatButtonActionsIndices)
.setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
.build()

val mediaOptions = CastMediaOptions.Builder()
.setNotificationOptions(notificationOptions)
.setExpandedControllerActivityClassName(
ExpandedControlsActivity::class.java.name
)
.build()

val receiverAppId = BuildConfig.CHROMECAST_APP_ID

return CastOptions.Builder()
.setReceiverApplicationId(receiverAppId)
.setCastMediaOptions(mediaOptions)
.build()
}

override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
return null
}
}

For more details: https://developers.google.com/cast/docs/android_sender/integrate#initialize_the_cast_context

Supported Interfaces for Casting

CastAuthUserConfig

Use this interface to register user data to the receiver:

NameTypeDescription
castDeviceIDstringcast device Id for the content
platformClientPlatformClientOverride PlatformClient if any. Otherwise, default Platform Client will be used

CastConfig Interface

Use this interface to load media to the receiver:

NameTypeDescription
mediaIDstringMedia Id for the content
titlestringtitle of the content
consumptionTypestringConsumptionType of the content
catalogTypestringCatalog of the content
imageURIstringurl for image
initialPlaybackPositionMsnumberinitial time for player
playbackModePlaybackModeplaybackmode for player, required for any live playback content
customBookmarkDataEpisodeBookmarkRecordcustomBookmarkData for Bookmark record
mediaTypeMediaTypeValuedefault value DASH for both the platform android or iOS
drmTypeDrmTypeValuedefault value WIDEVINE for both the platform android or iOS
startTimestringLive playback mode restart or catch up required to provide the value
endTimestringLive playback mode restart or catch up required to provide the value
eventIdstringeventId
urlParametersstringurl Parameters
seasonNumbernumberSeason number of the cast playback content
episodeNumbernumberEpisode number of the cast playback content
seriesTitlestringSeries title of the cast playback content
subtitlestringDescription or subtitle for the cast playback content
metadataMediaTypeMetadataMediaTypeMetadata type for setting up media metadata on the cast device

MetadataMediaType

The metadataMediaType property supports the following content types:

TypeDescriptionSupported Fields
MEDIA_TYPE_GENERICGeneric content (Default type)title, subtitle
MEDIA_TYPE_MOVIEMovie contenttitle, subtitle
MEDIA_TYPE_TV_SHOWTV show contenttitle, season, episode, series title
MEDIA_TYPE_MUSIC_TRACKMusic track (unsupported in current version)title
MEDIA_TYPE_PHOTOPhoto content (unsupported in current version)title
MEDIA_TYPE_AUDIOBOOK_CHAPTERAudiobook chapter (unsupported in current version)-
MEDIA_TYPE_USERUser-defined content (unsupported in current version)-

Note: The cast metadata properties (seasonNumber, episodeNumber, seriesTitle, subtitle, metadataMediaType) enhance the media information display on cast devices, providing a richer user experience during casting sessions.

CastMediaMetadata

The CastMediaMetadata represents the metadata related to casted content detals.

NameTypeDescription
mediaTypenumberType/category of the media being cast (implementation-specific numeric value).
titlestringPrimary display title for the current item.
subtitlestringSecondary text (e.g., episode title, tagline, additional context).
artiststringTrack artist name (typically for music content).
albumArtiststringAlbum-level artist (may differ from artist for compilations).
albumTitlestringAlbum name (music).
composerstringComposer name (if available).
trackNumbernumberTrack number within the album (music).
discNumbernumberDisc number within a multi-disc album (music).
imagesstring[]Image URLs associated with the content (thumbnails/posters).
seasonNumbernumberSeason number (TV/series content).
episodeNumbernumberEpisode number (TV/series content).
seriesTitlestringSeries title (TV/series content).
studiostringStudio / publisher name (if provided).
durationnumberTotal duration of the item.
liveStartTimeEpochnumberLive stream start time as an epoch timestamp (if the content is live).
liveOffsetnumberLive offset / delay from the live edge (units are implementation-specific; often seconds).

CastAuthorizer APIs

Configuration API

/**
* Provides an API to add a GCKStateListener at the SDK layer
*/
initWithConfig(): Promise<void>;

Note: After initializing the GCKCastContext singleton instance, you must call this API to check if isConfigured() returns true. Until then, the GCKCastContext instance is not considered fully initialized.

Cleanup API

/**
* Provides an API to end the casting session and deregister the GCKStateListener at the SDK layer.
*/
dispose: () => Promise<void>;

Media Control APIs

/**
* API responsible for loading media content onto the receiver (casting device).
*
* @param asset The media asset to be loaded; this parameter is required.
*/
castMedia(
asset: CastConfig,
headers?: { [key: string]: string },
metadata?: { [key: string]: any },
flAnalyticsData?: { [key: string]: string },
videoAnalyticsData?: { [key: string]: string}
): Promise<void>;

Input Arguments for castMedia

NameTypeDescription
assetCastConfigThe asset that must be loaded and played
headers{ [key: string]: string }HTTP Headers to be added to auth request
metadata{ [key: string]: any }TVOD data to be shared with chromecast receiver (optional)
flAnalyticsData{ [key: string]: string }The analytics attributes that has to be shared with chromecast receiver (optional)
videoAnalyticsData{ [key: string]: string }Custom video analytics metadata to be shared with chromecast receiver (optional)

Playback Control APIs

/**
* API responsible to get the cast player current playback state
*/
getCastPlaybackState: () => Promise<string>;

/**
* API responsible to get the current cast session state
*/
getCastState: () => Promise<string>;

/**
* API responsible for executing the play action sent from the sender to the receiver device.
*/
playCast(): Promise<void>;

/**
* API responsible for executing the pause action sent from the sender to the receiver device.
*/
pauseCast: () => Promise<void>;

/**
* API responsible for executing the stop action sent from the sender to the receiver device.
*/
stopCast: () => Promise<void>;

/**
* API responsible for register user device information in the receiver.
*/
authorizeUserData(config: CastAuthUserConfig): Promise<void>;

/**
* API responsible for get the GCKContext is initialized or not.
*/
isConfigured: () => Promise<boolean>;

/**
* API responsible for register cast player listeners.
*/
attachListener(): Promise<void>;

/**
* API responsible for unregister cast player listeners.
*/
detachListener(): Promise<void>;

/**
* API responsible for setting track variant for the current casting content.
*/
setCastPreferredTrackVariant(type: TrackVariantTypeValue, trackVariantInfo: TrackVariantInfo): Promise<void>;

/**
* Handles seek actions for the active cast content initiated from the sender.
*/
seek(seekPosition: number): Promise<void>;

/**
* Explicit API call required to launch the Cast expandable player screen.
*/
showExpandedControls(disableLiveProgressbar?: boolean): Promise<void>

Note: showExpandedControls API is implemented in the iOS Platform only.

Retrieve currently playing content metadata

getCurrentItem() to read the metadata of the item that is currently playing on the Cast receiver. Example usage for this is to display “Now Casting” details in your UI. Returns the cast metadata.

let currentItem = await castAuthorizer.getCurrentItem();

Jump to next item

jumpToNextItem() to advance playback to the next item in the Cast queue (similar to a “Next” / “Skip” action). Call this when your app offers a “Play Next” control, or when you want to programmatically move through a playlist/episode queue on the receiver.

await castAuthorizer.jumpToNextItem();

Cast Session Listeners

Use the CastEventListener and the following listener APIs to monitor the status of requested CastSession actions.

/**
* The callback is invoked when a cast session begins.
*/
castSessionStarted(param: any): void;

/**
* The callback is invoked when a cast session begins with error.
*/
castSessionStartFailed(param: any): void;

/**
* The callback is invoked when a cast session ended.
*/
castSessionEnded(): void;

/**
* The callback is invoked when a cast session ended with error.
*/
castSessionEndedError(param: any): void;

/**
* The callback is invoked when a cast session device registration.
*/
castSessionDeviceRegSuccess(): void;

/**
* The callback is invoked when a cast session device registration failed.
*/
castSessionDeviceRegErr(param: any): void;

/**
* The callback is invoked when a casting content playback error.
*/
castError(param: any): void;

/**
* The callback is invoked when a casting content current player playback state.
*/
castStateChange(param: any): void;

/**
* The callback is invoked when a casting content current player playback progress.
*/
castProgressUpdate(param: any): void;

/**
* The callback is invoked when a casting content current player playback of track variant updated.
* Note: this operation right now not supported.
*/
castTrackVariantChanged(param: any): void;

/**
* The callback is invoked when a casting content current player playback of all available tracks.
* Note: this operation right now not supported
*/
castTrackAvailabilityChanged(param: any): void;

/**
* This callback is invoked when any new content is pre-loaded. Publishes the content details of
* pre-loaded content.
*/
castPreloadStatusUpdated(param?: CastMediaMetadata): void;

Managing Listeners

Use cast Authorizer addListener api to register these listeners and removeListener api to unregister these listeners.

/**
* Adds a CastAuthorizer Listener
* @param listener
*/
addListener(
listener: CastSessionStartListeners | CastSessionEndListeners | CastSessionDeviceRegistrationListeners | CastSessionPlaybackListeners | CastEventListener,
): void;

/**
* Remove a CastAuthorizer Listener
* @param listener
*/
removeListener(
listener: CastSessionStartListeners | CastSessionEndListeners | CastSessionDeviceRegistrationListeners | CastSessionPlaybackListeners | CastEventListener,
): void;