React Native THEOplayer

Casting with Chromecast and Airplay

Overview

The basics of both Chromecast and Airplay are well-described in THEOplayer’s Knowledge Base. The react-native-theoplayer package has support for both.

This page first outlines the setup needed for Chromecast and Airplay, and then describes the player’s cast API and events subscription, which is common for both.

Chromecast

Setup

To enable Chromecast, react-native-theoplayer provides a cast module on the player (player.cast) that allows you to start/stop/join/leave chromecast sessions. The THEOplayer SDK will take care of the interactions with the cast receiver (communicating source updates, seeking, play/pause, …) and route all cast events through its API.

We can also recommend the react-native-google-cast package, which comes with native support for both iOS and Android. It is fully-featured and provides the possibility to manage devices and cast sessions, send new source descriptions and listen for cast events. It also includes a <CastButton> component that can be added to the app’s UI, as demonstrated in the example app.

<CastButton
  style={styles.castButton}
  tintColor={chromecastConnected ? '#ffc50f' : 'white'}
/>

This button represents a native media route button that shows the connection state and opens a device dialog when tapped. Using react-native-google-cast’s functionality does require some extra steps, such as communicating source updates, managing player status on both sender and receiver and handling the cast events. Our react-native-theoplayer integration already takes care of these tasks. The installation instructions for react-native-google-cast cover the steps to enable support for Chromecast in your app through that component.

For the rest of this document we assume that THEOplayer handles this logic. Enabling the player with Chromecast support requires a different approach on each platform.

Android The Android SDK is modular-based, so enabling Chromecast is limited to: 1. Including the cast extension in gradle by setting this flag in your `gradle.properties`: ```bash # Enable THEOplayer Extensions (default: disabled) THEOplayer_extensionCast = true ``` 2. Adding a native `CastOptionsProvider` class and referring to it from the app's Android manifest: ```xml ``` Check the example app for details on this setup. 3. Initializing the `CastContext` in your app's MainActivity: ```java @Override public void onCreate(Bundle savedInstanceState) { CastContext castContext = CastContext.getSharedInstance(this); } ```
iOS #### Add feature flag to config To enable Chromecast you need to add the "CHROMECAST" [feature flag](/react-native-theoplayer/doc/creating-minimal-app.html#getting-started-on-ios-and-tvos) to react-native-theoplayer.json (or theoplayer-config.json) #### iOS Configuration Specify NSBonjourServices in your Info.plist to allow local network discovery to succeed on iOS 14. You will need to add both _googlecast._tcp and _[your-app-id]._googlecast._tcp as services for device discovery to work properly. Update your applications info.plist with the following example NSBonjourServices definition, replacing "ABCD1234" with your appID. ```xml NSBonjourServices _googlecast._tcp _ABCD1234._googlecast._tcp ``` We also recommend that you customize the message shown in the Local Network prompt by adding an app-specific permission string in your app's Info.plist file for the NSLocalNetworkUsageDescription such as to describe Cast discovery and other discovery services. ```xml NSLocalNetworkUsageDescription ${PRODUCT_NAME} uses the local network to discover Cast-enabled devices on your WiFi network. ``` #### Combining with react-native-google-cast When using react-native-google-cast to render the CastButton, their documentation suggest to setup the CastContext as soon as possible. We noticed that waiting to prepare this context to a later point in time (i.e. till the AppId is bridged from RN) fails to display that CastButton. To prevent this follow the [instructions](https://react-native-google-cast.github.io/docs/getting-started/setup#ios) (or check our example application) to setup the GCKCastContext in the AppDelegate. The following options on the GCKCastOptions can be set as desired: 1. options.startDiscoveryAfterFirstTapOnCastButton = false; (set up how/when the castbutton is shown) 2. options.suspendSessionsWhenBackgrounded = false; (set up the connection response be when backgrounding the app) In addition, react-native-google-cast currently does not include a full featured (guest mode combined with Apple M1 support) setup of the Google Cast SDK. Our THEOplayerCastIntegration however does, but combining both results in a clash of dependencies (both delivering a GoogleCast.xcframework). To overcome this double dependency we suggest to use a [fork of react-native-google-cast](https://github.com/Danesz/react-native-google-cast/tree/feature/guestmode_apple_silicon) that depends on the same GoogleCast.xcframework. To achieve this: 1. Add the following to your applications podFile: ```ruby pod 'react-native-google-cast', :git => 'https://github.com/Danesz/react-native-google-cast.git', branch: 'feature/guestmode_apple_silicon' ``` 2. Prevent the autolinking of the original by updating your react-native.config.js with: ```json 'react-native-google-cast': { platforms: { ios: null, }, }, ```
Web The `react-native-google-cast` package has no support for Web yet. If the THEOplayer Web SDK's default UI is used however, the cast button will be included here and there is no need to install `react-native-google-cast`. The web page hosting the player just needs to load the Google cast sender module: ```html ```

THEOplayerView configuration

In the configuration of a THEOplayerView component you can set the receiver’s appID. This only makes sense on a Web platform, as for mobile platforms this value is already set natively through CastOptionsProvider on Android and AppDelegate on iOS:

const playerConfig: PlayerConfiguration = {
  cast: {
    chromecast: {
      appID: '<receiverAppID>'
    },
    strategy: 'auto'
  }
}

The example app sets appID to 'CC1AD845', which refers to Google’s default V3 receiver. This receiver implementation will know how to play the manifest/playlist URL sent by THEOplayer, but it does not have knowledge on how to handle any additional information from the source description provided through the MediaInfo.customData field. As a consequence, to enable playback of for example DRM-protected streams or ads, a custom receiver needs to be created that also handles these parts of the source description.

We refer to our sample-google-cast-v3-receiver repository for an example on how to interpret a THEOplayer source description and handle a custom DRM flow.

Cast strategy

The strategy property indicates the join strategy that will be used when starting/joining sessions:

In case the join strategy manual is chosen and a cast session is started by react-native-google-cast, it is necessary to explicitly let the player either join or take over the current session. This can be done by listening to the cast state and using the player’s cast API to either start or join:

import CastContext, {CastState} from "react-native-google-cast";

useEffect(() => {
  const subscription = CastContext.onCastStateChanged((castState) => {
    if (castState === CastState.CONNECTED) {
      // Let the player either start or join the session.
      player.cast.chromecast?.start();
    }
  })
  return () => subscription.remove()
}, [])

The example app uses strategy auto so the player will automatically send its source description when a session is created.

Providing metadata

The metadata object, as part of the source configuration, is used to send additional information to the receiver. Common fields include poster, title, subtitle, album and artist.

{
  "sources": [
    {
      "src": "https://cdn.theoplayer.com/video/dash/bbb_30fps/bbb_with_multiple_tiled_thumbnails.mpd",
      "type": "application/dash+xml"
    }
  ],
  "poster": "https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg",
  "metadata": {
    "title": "Big Buck Bunny",
    "subtitle": "a Peach Open Movie Project",
    "album": "React-Native THEOplayer demos",
    "artist": "THEOplayer"
  }
}
Chromecast
Casting a stream with metadata.

Airplay

For iOS and Web Safari, also Airplay is supported. Similar to chromecast, you can listen to or check the airplay cast state and use the player’s Airplay API to either start or join an Airplay session. When implementing a simple airplay button you can toggle Airplay using:

player.cast.airplay?.state().then((airplayCastState) => {
  const inConnection = airplayCastState === 'connected' || airplayCastState === 'connecting'
  if (inConnection) {
    player.cast.airplay?.stop()
  } else {
    player.cast.airplay?.start()
  }
})

Cast API

The THEOplayerView provides the THEOplayer API using the onPlayerReady callback, where you can access the CastAPI to control or start cast sessions, either Chromecast or Airplay.

Subscribing to Cast Events

The THEOplayerView provides the THEOplayer API using the onPlayerReady callback, where you can subscribe to cast events:

const onCastEvent = (event: CastEvent) => {
    console.log(event);
}

const onReady = (player: THEOplayer) => {
    player.addEventListener(PlayerEventType.CAST_EVENT, onCastEvent);
}

<THEOplayerView onPlayerReady={onReady}/>