Overview
With Google Cast technology, you can initiate and control streamed video content from your mobile devices to high-definition TV and home audio systems. From your app, tap the Cast button to stream your content on a big screen.
To build a Cast application, you need the following components:
-
A sender application - This resides on your mobile device, and detects receiver devices, establishes a secure connection, and mirrors your content. The sender app is the local player that is used to cast content to the receiver app on your Chromecast device. After you cast to the receiver app, you can think of it as a remote control for the Chromecast.
The sender app is provided by the Cast plugin for the Brightcove Native SDK for Android. You will learn about it in this topic.
-
A receiver application - This application runs on the Chromecast device. It can be thought of as a single-page HTML app with CSS and JavaScript assets.
For testing, follow these steps:
- Start with Google's Sample Cast Receiver
- Review Google Cast Apps documentation
For production use, this document will illustrate how to use the Brightcove Receiver v2.0.0.
Supported SDK version
To use the Cast plugin with the new Brightcove Receiver v2.0, you must use the Brightcove Native SDK for Android version 6.16.0 and above.
Understanding the Cast plugin
The Cast plugin is built on top of the new ExoPlayer Cast Extension and the Google Play Services Cast Framework. After adding the cast plugin dependency, gradle will pull the Play Services Cast Framework dependency, ExoPlayer Cast Extension dependency along with other needed dependencies.
The Cast plugin has been redesigned to minimize your effort when integrating with Video Cloud. When using Video Cloud, the BrightcoveCastMediaManager
class gathers information from the Video Cloud response, such as the Brightcove Video
and Source
objects, every time the EventType.SET_SOURCE
event is emitted. This information is cached and ready to use when the user selects play to queue the video.
Integrating the Cast plugin
There are two ways you can integrate your app with the Native SDK for Android Cast plugin. You can integrate with either the Brightcove Cast Receiver v2.0, or with the Google Cast Demo Receiver.
For either integration, you need to add this dependency to your app project:
implementation "com.brightcove.player:android-cast-plugin:${anpVersion}"
Using the Brightcove Cast Receiver v2.0
This integration is intended for those Brightcove customers who use Brightcove APIs to deliver their content.
For a complete code sample, see the BasicCastBrightcoveReceiverSampleApp.
Using the Google Cast Demo Receiver
This integration is intended for those Brightcove customers who are new to casting.
For a complete code sample, see the BasicCastGoogleReceiverSampleApp.
The Google Cast Demo receiver app is intentionally basic and easy to use, with the following constraints:
DRM is not supported.
Captions in any video configuration are not supported.
Multiple Audio Tracks are not supported.
Client-side Advertising is not supported.
Server-side Advertising is not supported.
Live and Live DVR streams are not supported.
Specifying your own Cast Receiver App Id
The BasicCastGoogleReceiverSampleApp sets a Google Demo Receiver App ID, which can be helpful for getting started and testing, but not for production.
To override this value with your Cast Receiver Application, define the following string value in the sample app’s strings.xml file:
<string name="cast_receiver_app_id">4F8B3483</string>
The Brightcove GoogleCastComponent
The GoogleCastComponent
class is the main class of the Brightcove Cast plugin. It instantiates the ExoPlayer CastPlayer and sets its listeners. It exposes some essential methods to load a video or to add it to the queue. The GoogleCastComponent
class also adds several Brightcove Event listeners to handle Activity and Fragment lifecycle events, as well as other event listeners that you can use to emit Media Info to load a Video to your Chromecast device.
The GoogleCastComponent
now uses a Builder pattern. In the Native SDK for Android versions before v6.16.0, you needed to instantiate the component and pass the Context
and EventEmitter
to the GoogleCastComponent
constructor. Then, you would set the component’s options in a series of separate method calls.
Starting with the Native SDK for Android v6.16.0, use the Builder pattern to create an instance of the GoogleCastComponent
and set its options, all within a single chain of Builder method calls.
CustomData
As with the GoogleCastComponent
, the CustomData
class uses a Builder pattern to instantiate the object and add properties to it. While the Brightcove Receiver can use CustomData
to retrieve videos from your Brightcove Catalog, it is not required to send a complete CustomData
object, such as for casting a remote asset. It is also important to note that when using the Google Demo Receiver, the use of CustomData
is not supported. For the purposes of this discussion, we will focus on CustomData
sent to the receiver used to retrieve the Video data from the Brightcove Catalog.
What is CustomData?
CustomData
is a JSON object contained in the MediaInfo
object. Its intended use is with the Brightcove Cast Receiver App v2.0.
CustomData with the Brightcove Receiver and Catalog Data
When integrating with the Brightcove Receiver, the CustomData
JSON object will take this form:
"customData": {
"accountId": "1234567890",
"analyticsParams": {
"application": "com.brightcove.player.test",
"user": "abcde1c44b951234"
},
"catalogParams": {
"adConfigId": null,
"type": "video",
"bcovAuthToken": null,
"id": "2345678901",
"policyKey": "BCpkPolicyKeyObject"
}
}
The CustomData
object example above contains all of the data elements necessary to cast a video from the Brightcove Receiver. This data is the same regardless of encryption, that is, there is no additional structure necessary for the license URL in the case of DRM videos.
You can also find an example of the CustomData
object in the BrightcoveCastBrightcoveReceiverSampleApp.
CustomData with the Google Demo Receiver
As stated above, CustomData
is not supported with the Google Demo Receiver.
BrightcoveCastMediaManager
It is possible to extend the BrightcoveCastMediaManager
, as shown above, to override its methods or to implement your own. For examples of extending the BrightcoveCastMediaManager class, see the following:
- Extend the BrightcoveCastMediaManager section
- BasicCastCustomRemoteVideoSampleApp
OptionsProvider
Next, you need to specify the OptionsProvider implementation for the Google Cast framework. The OptionsProvider
interface helps to set up several options needed to initialize the CastContext class. This is where you will set the Cast Receiver App ID. To learn more about integrating the OptionsProvider
, see Google’s Initialize the Cast Context document.
The Brightcove Cast plugin includes a DefaultOptionsProvider
class, where the Cast Receiver App ID is set through a string key set in the strings.xml resource file. For more details and to learn how to override it in your app, see the Using Your Own Cast Receiver App ID section above.
Whether you use the DefaultOptionsProvider
class or your own OptionsProvider
implementation, you need to set the OptionsProvider
implementation class name in your app’s AndroidManifest.xml file as a key-value pair metadata, as shown here:
<meta-data android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME" android:value="com.brightcove.cast.DefaultOptionsProvider" />
If you use the DefaultOptionsProvider
class, you can set the ExpandedControllerActivity
to turn on/off the Cast Notification by setting similar metadata information in your AndroidManifest.
Expanded Controller Activity
The ExpandedControllerActivity comes with the Google Cast library and allows you to control the video being cast on your Chromecast device. This class provides some customization flexibility. For example, there are five slots available to show buttons, where the third slot is reserved for the non-configurable Play button. The rest of the buttons can be set as other predefined buttons or as your own customized buttons.
The Brightcove Cast plugin provides the subclass DefaultExpandedControllerActivity
. We have enabled the following buttons in the following order:
- Closed Captions
- Skip Previous
- Play
- Skip Next
- Mute Toggle
In addition, the Seek Bar sets the same default drawable as the one used in the standard BrightcoveMediaController
:
- The Progress Drawable:
R.drawable.default_scrubber_progress_horizontal
- The Thumb Drawable:
R.drawable.default_scrubber_thumb
To learn how to customize the Seek Bar, see the SeekBarColorsSampleApp.
In order to set the DefaultExpandedControllerActivity
or your own ExpandedControllerActivity
, set the following metadata in your AndroidManifest.xml file:
<meta-data android:name="com.brightcove.cast.DefaultOptionsProvider.EXPANDED_CONTROLLER_ACTIVITY_CLASS_NAME"
android:value="com.brightcove.cast.DefaultExpandedControllerActivity" />
Cast Notification
When the Cast Notification is enabled, the notification will appear when you cast a video and put your app in the background; for example, after pressing the home key.
<meta-data android:name="com.brightcove.cast.DefaultOptionsProvider.NOTIFICATION_TARGET_ACTIVITY_CLASS_NAME"
android:value="com.brightcove.cast.BrightcoveControllerActivity" />
If you do not provide com.brightcove.cast.DefaultOptionsProvider.NOTIFICATION_TARGET_ACTIVITY_CLASS_NAME or if the value has an invalid Activity name, the Cast Notification will be turned off.
The Cast Button
The cast button allows you to select a Chromecast device in the same network as your device, and enables you to connect and create a session. To add the Cast Button to your application, follow Google’s Integrate Cast: Add a Cast Button document.
The Brightcove Cast plugin provides a utility method to easily setup the Cast button. This is useful when you just want to add the Cast button to the Activity/Fragment menu. See the following code for details:
//Activity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
GoogleCastComponent.setUpMediaRouteButton(MainActivity.this, menu);
return true;
}
The Mini Controller
The Mini Controller is a Fragment that gets attached to your Activity, usually located in the bottom of the layout. The Mini Controller allows you to play and pause the video, and indicates when a video is playing in your Chromecast device. When the Mini Controller is clicked, the Expanded Controller will be launched.
To enable the Mini Controller, add the following code to your Activity’s layout.
<fragment
android:id="@+id/castMiniController"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:visibility="gone"
class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment" />
To learn best practices with the Mini Controller, see the Design Checklist: Sender Mini Controller document. For implementation details, see the Integrate Cast: Add Mini Controller document.
Advanced Topics
Listening for Cast session
If you want your app to react when the Cast connection starts or ends, you can add the GoogleCastEventType.CAST_SESSION_STARTED
or GoogleCastEventType.CAST_SESSION_ENDED
event listeners as shown here:
eventEmitter.on(GoogleCastEventType.CAST_SESSION_STARTED, new EventListener() {
@Override
public void processEvent(Event event) {
// Session Started
}
});
eventEmitter.on(GoogleCastEventType.CAST_SESSION_ENDED, new EventListener() {
@Override
public void processEvent(Event event) {
// Session Ended
}
});
Alternatively, you can call GoogleCastComponent.isSessionAvailable()
to check for an available session.
Casting a Video
In order to cast a Video to Chromecast after a successful connection, you can either use the EventEmitter and emit the Media Info information or you can directly use the GoogleCastComponent
methods.
If you prefer to emit the Media Info you can use the following events:
GoogleCastEventType.LOAD_MEDIA_INFO
GoogleCastEventType.LOAD_MEDIA_QUEUE_ITEM
GoogleCastEventType.ADD_MEDIA_INFO
GoogleCastEventType.ADD_MEDIA_QUEUE_ITEM
The following table shows the expected properties for each event:
Event Name | Properties | |
---|---|---|
Key | Value Class type | |
LOAD_MEDIA_INFO |
GoogleCastComponent.CAST_MEDIA_INFO GoogleCastComponent.CAST_MEDIA_PLAY_POSITION |
MediaInfo Integer |
LOAD_MEDIA_QUEUE_ITEM |
GoogleCastComponent.CAST_MEDIA_QUEUE_ITEM |
MediaQueueItem |
ADD_MEDIA_INFO |
GoogleCastComponent.CAST_MEDIA_INFO GoogleCastComponent.CAST_MEDIA_PLAY_POSITION |
MediaInfo Integer |
ADD_MEDIA_QUEUE_ITEM |
GoogleCastComponent.CAST_MEDIA_QUEUE_ITEM |
MediaQueueItem |
Alternatively, you can use the following GoogleCastComponent
methods:
-
public void loadMediaInfo(MediaInfo mediaInfo, long positionMs)
-
public void loadMediaInfo(MediaInfo mediaInfo)
-
public PendingResult<RemoteMediaClient.MediaChannelResult> loadItem(MediaQueueItem mediaQueue, int playheadPosition)
-
public PendingResult<RemoteMediaClient.MediaChannelResult> addItems(MediaQueueItem... mediaQueue )
Changing the default MediaInfo data
By default, the Cast plugin gathers information about the current Video and Source object emitted by the EventType.SET_SOURCE event
. If you want to change or add additional information, such as adding a custom JSON object to your MediaInfo
that your App receiver understands, you can do it by overwriting the loadMediaInfo()
and addMediaInfo()
methods from the BrightcoveCastMediaManager
. Then, your BrightcoveCastMediaManager
subclass is passed as a constructor parameter to the GoogleCastComponent
class.
Inside these methods, you can create your MediaInfo
objects and emit the appropriate events as shown previously. Be sure to check com.brightcove.cast.util.CastMediaUtil
, as it provides some utility methods to create a MediaInfo
from the Video and Source objects.
Configuring the Cast MediaController
To change the controller layout that appears in your Brightcove Video View when a Cast session has started, follow these steps.
Extend the BrightcoveCastMediaManager
To change the default behavior of the BrightcoveCastMediaManager
, create a subclass and overwrite some key methods:
-
public void updateBrightcoveMediaController(boolean isRemote)
This method is called by the
GoogleCastComponent
when the session changes; that is, when the session has started or has ended. When the session has started, theisRemote
parameter will betrue
and thesetupRemoteController
method is called. Otherwise, theisRemote
will befalse
and theresetToLocalController
is called. -
protected void setupRemoteController()
This method emits the event
EventType.SET_MEDIA_CONTROLLER_CONFIG
with theMediaControllerConfig
object. We will talk more aboutMediaControllerConfig
later in this section. This method also listens to theBrightcoveMediaController.CONTROL_BAR_CREATED
event and reacts by calling thesetupBrightcoveControlBar
method. -
protected void resetToLocalController()
This method is responsible for resetting the
BrightcoveMediaController
to the original controller layout by emitting theEventType.RESTORE_DEFAULT_MEDIA_CONTROLLER
. -
protected void setupBrightcoveControlBar(BrightcoveControlBar controlBar)
Once the
BrightcoveMediaController
has been recreated with the layout provided in theMediaControllerConfig
, you will get access to theBrightcoveControlBar
view. From here, you can access your UI views, like Buttons, where you can addOnClickListener
's to them.
Set the MediaControllerConfig
The MediaControllerConfig
is a configuration class that you can use to change the default control layout of the BrightcoveMediaController
class. In this class, you can set the layout and the OnTouchListener
. Once created and configured, you can emit this object as shown below:
Map<String, Object> properties = new HashMap<>();
properties.put(Event.MEDIA_CONTROLLER_CONFIG, myMediaControllerConfig);
eventEmitter.emit(EventType.SET_MEDIA_CONTROLLER_CONFIG,properties);
The default MediaControllerConfig
object sets the R.layout.cast_media_controller
as the layout with a single Play button. When clicked, it will open a dialog with two options:
- Play Now - When selected, the
loadMediaInfo()
method is called and the video will load and play in Chromecast. - Add to Queue - When selected, the
addMediaInfo()
method is called and the video is added to the end of the queue.
Overwrite the control bar setup
When your media controller layout is set by emitting the MediaControllerConfig
, the BrightcoveControlBar
view will be created and the BrightcoveCastMediaManager.setupBrightcoveControlBar()
method will be called. It’s here where you can get your UI components by Id and add the appropriate listeners.
@Override
protected void setupBrightcoveControlBar(BrightcoveControlBar controlBar) {
Button playButton = controlBar.findViewById(R.id.cast_play);
if (playButton != null) {
playButton.setOnClickListener(new View.OnClickListener() {...});
}
}
Known Issues
Android 9
When using Chromecast with Android 9 and above, you need to include a FOREGROUND_SERVICE
permission. This allows the app to use notifications to control a casting session when the app is backgrounded and brought back to the foreground.
The uses-permission
tag should be added to the app's AndroidManifest.xml file, as follows:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
Google Play services
The Casting connection may not be created if the sender’s Google Play Services version is not up to date. When the sender’s Google Play Services, in particular the Cast Services framework, are out of date, you may be unsuccessful in creating a Cast connection. This is remedied by updating the sender’s Google Play Services through the Google Play Store.