1. Descripción general
En este codelab, aprenderás a modificar una app de video web existente para transmitir contenido en un dispositivo compatible con Google Cast.
¿Qué es Google Cast?
Google Cast permite a los usuarios transmitir contenido desde un dispositivo móvil a una TV. De esa manera, los usuarios pueden usar su dispositivo móvil como control remoto de modo que se reproduzca contenido multimedia en la TV.
El SDK de Google Cast posibilita que extiendas tu app para controlar una TV o un sistema de sonido. Este SDK te permitirá agregar los componentes de la IU necesarios según la lista de tareas de diseño de Google Cast.
Te proporcionamos la lista de tareas de diseño de Google Cast con el fin de que la experiencia del usuario de Cast resulte sencilla y predecible en todas las plataformas compatibles.
¿Qué compilaremos?
Cuando completes este codelab, tendrás una app de video web de Chrome que podrá transmitir videos a un dispositivo Google Cast.
Qué aprenderás
- Cómo agregar el SDK de Google Cast a una app de video de muestra
- Cómo agregar el botón para transmitir a fin de seleccionar un dispositivo Google Cast
- Cómo conectarse a un dispositivo de transmisión e iniciar un receptor de contenido multimedia
- Cómo transmitir un video
- Cómo integrar Cast Connect
Requisitos
- La versión más reciente del navegador Google Chrome
- Servicio de hosting HTTPS, como Firebase Hosting o ngrok.
- Un dispositivo Google Cast, como Chromecast o Android TV, que esté configurado con acceso a Internet
- Una TV o un monitor con entrada HDMI
- Se requiere un Chromecast con Google TV para probar la integración de Cast Connect, pero es opcional para el resto del codelab. Si no tienes una, puedes omitir el paso Agregar compatibilidad con Cast Connect al final de este instructivo.
Experiencia
- Debes tener conocimientos previos sobre desarrollo web.
- También deberás tener experiencia como usuario de TV :)
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia con la compilación de apps web?
¿Cómo calificarías tu experiencia cuando miras TV?
2. Obtén el código de muestra
Puedes descargar el código de muestra completo a tu computadora…
y descomprimir el archivo ZIP que se descargó.
3. Ejecuta la app de muestra
Primero, veamos el aspecto de la app de muestra completa. La app es un reproductor de video básico. El usuario podrá seleccionar un video de una lista y, a continuación, reproducirlo en un dispositivo local o transmitirlo a uno compatible con Google Cast.
Para poder usar la versión completa, debe estar alojada.
Si no tienes un servidor disponible, puedes usar Firebase Hosting o ngrok.
Ejecuta el servidor
Una vez que hayas configurado el servicio que elijas, navega a app-done
y, luego, inicia tu servidor.
En tu navegador, visita la URL HTTPS de la muestra que alojaste.
- Deberías ver la app de video.
- Haz clic en el botón para transmitir y selecciona tu dispositivo Google Cast.
- Selecciona un video y haz clic en el botón de reproducción.
- El video comenzará a reproducirse en tu dispositivo Google Cast.
Haz clic en el botón de pausa del elemento de video para pausarlo en la app receptora. Haz clic en el botón de reproducción del elemento de video para seguir reproduciendo el video nuevamente.
Haz clic en el botón para transmitir y deja de transmitir al dispositivo Google Cast.
Antes de continuar, detén el servidor.
4. Prepara el proyecto inicial
Debemos agregar compatibilidad con Google Cast a la app inicial que descargaste. A continuación, se incluye la terminología de Google Cast que usaremos en este codelab:
- una app emisora se ejecuta en un dispositivo móvil o una laptop.
- una app receptora se ejecuta en el dispositivo Google Cast.
Ya tienes todo listo para compilar sobre el proyecto inicial usando tu editor de texto favorito:
- Selecciona el directorio
app-start
de la descarga del código de muestra. - Ejecuta la app con tu servidor y explora la IU.
Ten en cuenta que, a medida que trabajes en este codelab, deberás volver a alojar la muestra en tu servidor en función del servicio.
Diseño de apps
La app recuperará una lista de videos de un servidor web remoto y proporcionará una lista para que el usuario explore. Los usuarios podrán seleccionar un video de forma que vean los detalles o reproducirlo localmente en el dispositivo móvil.
La app consta de una vista principal, definida en index.html
, y el controlador principal, CastVideos.js.
index.html
Este archivo html declara casi toda la IU de la aplicación web.
Hay algunas secciones de vistas. Tenemos nuestro div#main_video
, que contiene el elemento de video. En relación con nuestro div de video, contamos con div#media_control
, que define todos los controles del elemento de video. Debajo, se encuentra media_info
, que muestra los detalles del video en la vista. Por último, el elemento div carousel
muestra una lista de videos en un elemento div.
El archivo index.html
también inicia el SDK de Cast y le indica a la función CastVideos
que cargue.
La mayor parte del contenido que propagará estos elementos se define, inserta y controla en CastVideos.js
. Echemos un vistazo.
CastVideos.js
Esta secuencia de comandos administra toda la lógica de la aplicación web de videos de transmisión. La lista de videos y sus metadatos asociados definidos en CastVideos.js
se encuentran en un objeto llamado mediaJSON
.
Hay algunas secciones principales que, en conjunto, se encargan de administrar y reproducir el video de forma local y remota. En términos generales, es una aplicación web bastante sencilla.
CastPlayer
es la clase principal que administra toda la app, configura el reproductor, selecciona contenido multimedia y vincula eventos a PlayerHandler
para reproducir contenido multimedia. CastPlayer.prototype.initializeCastPlayer
es el método que configura todas las funciones de Cast. CastPlayer.prototype.switchPlayer
cambia el estado entre reproductores locales y remotos. CastPlayer.prototype.setupLocalPlayer
y CastPlayer.prototype.setupRemotePlayer
inicializan reproductores locales y remotos.
PlayerHandler
es la clase responsable de administrar la reproducción de contenido multimedia. Existen otros métodos responsables de los detalles de la administración del contenido multimedia y la reproducción.
Preguntas frecuentes
5. Agrega el botón para transmitir
Una app compatible con Cast muestra el botón para transmitir en el elemento de video. Al hacer clic en ese botón, se mostrará la lista de dispositivos de transmisión que un usuario puede seleccionar. Si el usuario estaba reproduciendo contenido de forma local en el dispositivo emisor, al seleccionar un dispositivo de transmisión podrá iniciar o reanudar la reproducción en ese dispositivo. En cualquier momento de una sesión de transmisión, el usuario podrá hacer clic en el botón para transmitir y dejar de transmitir tu aplicación al dispositivo de transmisión. El usuario debe poder conectarse al dispositivo de transmisión o desconectarse de él desde cualquier pantalla de la aplicación, como se describe en la lista de tareas de diseño de Google Cast.
Configuración
El proyecto inicial requiere las mismas dependencias y configuración que la de la app de ejemplo completa, pero esta vez aloja el contenido de app-start
.
En tu navegador, visita la URL https
de la muestra que alojaste.
Recuerda que, a medida que realices cambios, deberás volver a alojar la muestra en tu servidor en función del servicio.
Inicialización
El framework de Cast tiene un objeto singleton global, el CastContext
, que coordina todas las actividades del framework. Este objeto debe inicializarse con anticipación en el ciclo de vida de la aplicación, por lo general, se llama desde una devolución de llamada asignada a window['__onGCastApiAvailable']
, que se llama después de que se carga el SDK de Cast, y está disponible para su uso. En este caso, se llama a CastContext
en CastPlayer.prototype.initializeCastPlayer
, al que se llama desde la devolución de llamada mencionada anteriormente.
Cuando se inicializa CastContext
, se debe proporcionar un objeto JSON options
. Esta clase contiene opciones que afectan el comportamiento del framework. La más importante es el ID de aplicación receptora, que se usa para filtrar la lista de dispositivos de transmisión disponibles para mostrar solo los dispositivos que pueden ejecutar la app especificada y para iniciar la aplicación receptora cuando se inicia una sesión de transmisión.
Cuando desarrolles tu propia app compatible con Cast, tendrás que registrarte como desarrollador de Cast y, luego, obtener el ID de aplicación correspondiente a tu app. Para este codelab, usaremos un ID de app de muestra.
Agrega el siguiente código a index.html
al final de la sección body
:
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
Agrega el siguiente código a index.html
para inicializar la app de CastVideos
y también inicializar CastContext
:
<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
castPlayer.initializeCastPlayer();
}
};
</script>
Ahora, debemos agregar un nuevo método en CastVideos.js
, que corresponde al método que acabamos de llamar en index.html
. Agreguemos un nuevo método, llamado initializeCastPlayer
, que establece las opciones en CastContext e inicializa nuevos RemotePlayer
y RemotePlayerControllers
:
/**
* This method sets up the CastContext, and a few other members
* that are necessary to play and control videos on a Cast
* device.
*/
CastPlayer.prototype.initializeCastPlayer = function() {
var options = {};
// Set the receiver application ID to your own (created in
// the Google Cast Developer Console), or optionally
// use the chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID
options.receiverApplicationId = 'C0868879';
// Auto join policy can be one of the following three:
// ORIGIN_SCOPED - Auto connect from same appId and page origin
// TAB_AND_ORIGIN_SCOPED - Auto connect from same appId, page origin, and tab
// PAGE_SCOPED - No auto connect
options.autoJoinPolicy = chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED;
cast.framework.CastContext.getInstance().setOptions(options);
this.remotePlayer = new cast.framework.RemotePlayer();
this.remotePlayerController = new cast.framework.RemotePlayerController(this.remotePlayer);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED,
this.switchPlayer.bind(this)
);
};
Por último, debemos crear las variables para RemotePlayer
y RemotePlayerController
:
var CastPlayer = function() {
//...
/* Cast player variables */
/** @type {cast.framework.RemotePlayer} */
this.remotePlayer = null;
/** @type {cast.framework.RemotePlayerController} */
this.remotePlayerController = null;
//...
};
Botón para transmitir
Ahora que se inicializó CastContext
, debemos agregar el botón para transmitir a fin de permitir que el usuario seleccione un dispositivo de transmisión. El SDK de Cast proporciona un componente de botón para transmitir llamado google-cast-launcher
con un ID de "castbutton"
. Se puede agregar al elemento de video de la aplicación con solo agregar un button
en la sección media_control
.
Así se verá el elemento del botón:
<google-cast-launcher id="castbutton"></google-cast-launcher>
Agrega el siguiente código a index.html
en la sección media_control
:
<div id="media_control">
<div id="play"></div>
<div id="pause"></div>
<div id="progress_bg"></div>
<div id="progress"></div>
<div id="progress_indicator"></div>
<div id="fullscreen_expand"></div>
<div id="fullscreen_collapse"></div>
<google-cast-launcher id="castbutton"></google-cast-launcher>
<div id="audio_bg"></div>
<div id="audio_bg_track"></div>
<div id="audio_indicator"></div>
<div id="audio_bg_level"></div>
<div id="audio_on"></div>
<div id="audio_off"></div>
<div id="duration">00:00:00</div>
</div>
A continuación, actualiza la página en el navegador Chrome. Deberías ver un botón para transmitir en el elemento de video y, cuando hagas clic en él, se mostrarán los dispositivos de transmisión en tu red local. El navegador Chrome administra automáticamente la detección de dispositivos. Selecciona tu dispositivo de transmisión. La app receptora de muestra se cargará en él.
No se estableció compatibilidad con la reproducción de contenido multimedia, por lo que aún no puedes reproducir videos en el dispositivo de transmisión. Haz clic en el botón para transmitir a fin de detener la transmisión.
6. Transmite contenido de video
Extenderemos la app de muestra de modo que también reproduzca videos de forma remota en un dispositivo de transmisión. Para ello, tenemos que escuchar los diferentes eventos generados por el framework de Cast.
Transmisión de contenido multimedia
En términos generales, si quieres reproducir contenido multimedia en un dispositivo de transmisión, debe ocurrir lo siguiente:
- Crea un objeto
MediaInfo
JSON
desde el SDK de Cast que modela un elemento multimedia. - El usuario se conecta al dispositivo de transmisión para iniciar la aplicación receptora.
- Cargar el objeto
MediaInfo
en tu receptor y reproducir el contenido - Realizar un seguimiento del estado del contenido multimedia
- Enviar comandos de reproducción al receptor según las interacciones del usuario
El paso 1 equivale a asignar un objeto a otro. MediaInfo
es algo que el SDK de Cast entiende y mediaJSON
es el encapsulamiento de nuestra app para un elemento multimedia. podemos asignar fácilmente un mediaJSON
a un MediaInfo
. Ya realizamos el paso 2 en la sección anterior. El paso 3 es fácil de realizar con el SDK de Cast.
La app de ejemplo CastPlayer
ya distingue entre la reproducción local y la remota en el método switchPlayer
:
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
//...
En este codelab, no es importante que comprendas exactamente cómo funciona toda la lógica del reproductor de muestra. Sin embargo, es importante comprender que el reproductor multimedia de tu app deberá modificarse para que tenga en cuenta la reproducción local y remota.
Por el momento, el reproductor local siempre estará en el estado de reproducción local porque aún no conoce los estados de transmisión. Deberemos actualizar la IU en función de las transiciones de estado que ocurran en el framework de Cast. Por ejemplo, si comenzamos a transmitir, deberemos detener la reproducción local e inhabilitar algunos controles. Del mismo modo, si dejamos de transmitir contenido cuando estamos en este controlador de vista, debemos hacer la transición a la reproducción local. Para ello, tenemos que escuchar los diferentes eventos generados por el framework de Cast.
Administración de sesiones de transmisión
En el framework de Cast, una sesión de transmisión combina los pasos para conectarse a un dispositivo, iniciar (o unirse a una sesión existente), conectarse a una aplicación receptora e inicializar un canal de control de contenido multimedia, si corresponde. El canal de control de contenido multimedia es la forma en que el framework de Cast envía y recibe mensajes relacionados con la reproducción de contenido multimedia de la app receptora.
La sesión de transmisión se iniciará automáticamente cuando el usuario seleccione un dispositivo desde el botón para transmitir y se detendrá automáticamente cuando el usuario se desconecte. El framework de Cast también administra automáticamente la reconexión a la sesión de un receptor debido a problemas de red.
El CastSession
administra las sesiones de transmisión, a las que se puede acceder a través de cast.framework.CastContext.getInstance().getCurrentSession()
. Las devoluciones de llamada de EventListener
se pueden usar para supervisar los eventos de sesión, como la creación, la suspensión, la reanudación y la finalización.
En nuestra aplicación actual, toda la administración de la sesión y el estado se controla por nosotros en el método setupRemotePlayer
. Para comenzar a configurar eso en tu app, agrega el siguiente código a tu CastVideos.js
:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
Aún necesitamos vincular todos los eventos de las devoluciones de llamada y controlar todos los eventos entrantes. Esta tarea es bastante sencilla, así que veámosla:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
// Add event listeners for player changes which may occur outside sender app
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_PAUSED_CHANGED,
function() {
if (this.remotePlayer.isPaused) {
this.playerHandler.pause();
} else {
this.playerHandler.play();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_MUTED_CHANGED,
function() {
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
} else {
this.playerHandler.unMute();
}
}.bind(this)
);
this.remotePlayerController.addEventListener(
cast.framework.RemotePlayerEventType.VOLUME_LEVEL_CHANGED,
function() {
var newVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = newVolume + 'px';
p.style.marginTop = -newVolume + 'px';
}.bind(this)
);
// This object will implement PlayerHandler callbacks with
// remotePlayerController, and makes necessary UI updates specific
// to remote playback
var playerTarget = {};
playerTarget.play = function () {
if (this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
var vi = document.getElementById('video_image');
vi.style.display = 'block';
var localPlayer = document.getElementById('video_element');
localPlayer.style.display = 'none';
}.bind(this);
playerTarget.pause = function () {
if (!this.remotePlayer.isPaused) {
this.remotePlayerController.playOrPause();
}
}.bind(this);
playerTarget.stop = function () {
this.remotePlayerController.stop();
}.bind(this);
playerTarget.getCurrentMediaTime = function() {
return this.remotePlayer.currentTime;
}.bind(this);
playerTarget.getMediaDuration = function() {
return this.remotePlayer.duration;
}.bind(this);
playerTarget.updateDisplayMessage = function () {
document.getElementById('playerstate').style.display = 'block';
document.getElementById('playerstatebg').style.display = 'block';
document.getElementById('video_image_overlay').style.display = 'block';
document.getElementById('playerstate').innerHTML =
this.mediaContents[ this.currentMediaIndex]['title'] + ' ' +
this.playerState + ' on ' + castSession.getCastDevice().friendlyName;
}.bind(this);
playerTarget.setVolume = function (volumeSliderPosition) {
// Add resistance to avoid loud volume
var currentVolume = this.remotePlayer.volumeLevel;
var p = document.getElementById('audio_bg_level');
if (volumeSliderPosition < FULL_VOLUME_HEIGHT) {
var vScale = this.currentVolume * FULL_VOLUME_HEIGHT;
if (volumeSliderPosition > vScale) {
volumeSliderPosition = vScale + (pos - vScale) / 2;
}
p.style.height = volumeSliderPosition + 'px';
p.style.marginTop = -volumeSliderPosition + 'px';
currentVolume = volumeSliderPosition / FULL_VOLUME_HEIGHT;
} else {
currentVolume = 1;
}
this.remotePlayer.volumeLevel = currentVolume;
this.remotePlayerController.setVolumeLevel();
}.bind(this);
playerTarget.mute = function () {
if (!this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.unMute = function () {
if (this.remotePlayer.isMuted) {
this.remotePlayerController.muteOrUnmute();
}
}.bind(this);
playerTarget.isMuted = function() {
return this.remotePlayer.isMuted;
}.bind(this);
playerTarget.seekTo = function (time) {
this.remotePlayer.currentTime = time;
this.remotePlayerController.seek();
}.bind(this);
this.playerHandler.setTarget(playerTarget);
// Setup remote player volume right on setup
// The remote player may have had a volume set from previous playback
if (this.remotePlayer.isMuted) {
this.playerHandler.mute();
}
var currentVolume = this.remotePlayer.volumeLevel * FULL_VOLUME_HEIGHT;
var p = document.getElementById('audio_bg_level');
p.style.height = currentVolume + 'px';
p.style.marginTop = -currentVolume + 'px';
this.hideFullscreenButton();
this.playerHandler.play();
};
Carga de contenido multimedia
En el SDK de Cast, RemotePlayer
y RemotePlayerController
proporcionan un conjunto de APIs convenientes para administrar la reproducción de contenido multimedia remoto en la app receptora. En el caso de una CastSession
que admita la reproducción de contenido multimedia, el SDK creará automáticamente las instancias de RemotePlayer
y RemotePlayerController
. Para acceder a ellos, crea instancias de cast.framework.RemotePlayer
y cast.framework.RemotePlayerController
respectivamente, como se mostró antes en el codelab.
A continuación, debemos cargar el video seleccionado actualmente en la app receptora. Para ello, debemos crear un objeto MediaInfo para que el SDK procese y pase la solicitud. Para ello, agrega el siguiente código a setupRemotePlayer
:
/**
* Set the PlayerHandler target to use the remote player
*/
CastPlayer.prototype.setupRemotePlayer = function () {
//...
playerTarget.load = function (mediaIndex) {
console.log('Loading...' + this.mediaContents[mediaIndex]['title']);
var mediaInfo = new chrome.cast.media.MediaInfo(
this.mediaContents[mediaIndex]['sources'][0], 'video/mp4');
mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata();
mediaInfo.metadata.metadataType = chrome.cast.media.MetadataType.GENERIC;
mediaInfo.metadata.title = this.mediaContents[mediaIndex]['title'];
mediaInfo.metadata.images = [
{'url': MEDIA_SOURCE_ROOT + this.mediaContents[mediaIndex]['thumb']}];
var request = new chrome.cast.media.LoadRequest(mediaInfo);
castSession.loadMedia(request).then(
this.playerHandler.loaded.bind(this.playerHandler),
function (errorCode) {
this.playerState = PLAYER_STATE.ERROR;
console.log('Remote media load error: ' +
CastPlayer.getErrorMessage(errorCode));
}.bind(this));
}.bind(this);
//...
};
Ahora agrega un método para alternar entre la reproducción local y la remota:
/**
* This is a method for switching between the local and remote
* players. If the local player is selected, setupLocalPlayer()
* is run. If there is a cast device connected we run
* setupRemotePlayer().
*/
CastPlayer.prototype.switchPlayer = function() {
this.stopProgressTimer();
this.resetVolumeSlider();
this.playerHandler.stop();
this.playerState = PLAYER_STATE.IDLE;
if (cast && cast.framework) {
if (this.remotePlayer.isConnected) {
this.setupRemotePlayer();
return;
}
}
this.setupLocalPlayer();
};
Por último, agrega un método para controlar los mensajes de error de Cast:
/**
* Makes human-readable message from chrome.cast.Error
* @param {chrome.cast.Error} error
* @return {string} error message
*/
CastPlayer.getErrorMessage = function(error) {
switch (error.code) {
case chrome.cast.ErrorCode.API_NOT_INITIALIZED:
return 'The API is not initialized.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CANCEL:
return 'The operation was canceled by the user' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.CHANNEL_ERROR:
return 'A channel to the receiver is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.EXTENSION_MISSING:
return 'The Cast extension is not available.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.INVALID_PARAMETER:
return 'The parameters to the operation were not valid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.RECEIVER_UNAVAILABLE:
return 'No receiver was compatible with the session request.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.SESSION_ERROR:
return 'A session could not be created, or a session was invalid.' +
(error.description ? ' :' + error.description : '');
case chrome.cast.ErrorCode.TIMEOUT:
return 'The operation timed out.' +
(error.description ? ' :' + error.description : '');
}
};
Ahora, ejecuta la app. Conéctate a tu dispositivo de transmisión y comienza a reproducir un video. Deberías ver que el video se reproduce en el receptor.
7. Cómo agregar compatibilidad con Cast Connect
La biblioteca de Cast Connect permite que las aplicaciones emisoras existentes se comuniquen con las aplicaciones de Android TV a través del protocolo de transmisión. Cast Connect se basa en la infraestructura de transmisión y tu app para Android TV actúa como receptora.
Dependencias
- Navegador Chrome versión M87 o posterior
Configurar Android Receiver Compatible
Para iniciar la aplicación para Android TV, también conocida como Android Receiver, debemos establecer la marca androidReceiverCompatible
como verdadera en el objeto CastOptions
.
Agrega el siguiente código a tu CastVideos.js
en la función initializeCastPlayer
:
var options = {};
...
options.androidReceiverCompatible = true;
cast.framework.CastContext.getInstance().setOptions(options);
Configurar credenciales de lanzamiento
En el lado del remitente, puedes especificar CredentialsData
para representar quién se une a la sesión. credentials
es una cadena que el usuario puede definir, siempre que la app de ATV pueda comprenderla. El CredentialsData
solo se pasa a la app para Android TV durante el inicio o el momento de unión. Si la vuelves a configurar mientras estás conectado, no se transmitirá a la app de Android TV.
Para configurar las credenciales de lanzamiento, se debe definir CredentialsData
en cualquier momento después de establecer las opciones de inicio.
Agrega el siguiente código a tu clase CastVideos.js
en la función initializeCastPlayer
:
cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...
Configurar credenciales en una solicitud de carga
En caso de que tu app de receptor web y tu app de Android TV controlen credentials
de manera diferente, es posible que debas definir credenciales separadas para cada una. Para solucionarlo, agrega el siguiente código a tu CastVideos.js
en playerTarget.load
en la función setupRemotePlayer
:
...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...
Según la app receptora a la que la emisora transmita, el SDK ahora controlará automáticamente las credenciales que se deben usar para la sesión actual.
Prueba Cast Connect
Pasos para instalar el APK de Android TV en Chromecast con Google TV:
- Busca la dirección IP de tu dispositivo Android TV. Generalmente, está disponible en Configuración > Redes y Internet > (Nombre de la red a la que está conectado tu dispositivo). A la derecha, se mostrarán los detalles y la IP del dispositivo en la red.
- Usa la dirección IP para que tu dispositivo se conecte a través de ADB desde la terminal:
$ adb connect <device_ip_address>:5555
- Desde la ventana de tu terminal, navega a la carpeta de nivel superior de las muestras de codelab que descargaste al comienzo de este codelab. Por ejemplo:
$ cd Desktop/chrome_codelab_src
- Instala el archivo .apk en esta carpeta en tu Android TV ejecutando lo siguiente:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
- Ahora deberías poder ver una app con el nombre Transmitir videos en el menú Tus apps de tu dispositivo Android TV.
- Ejecuta el código de remitente web actualizado y establece una sesión de transmisión con tu dispositivo Android TV. Para ello, presiona el ícono de transmisión o selecciona
Cast..
en el menú desplegable del navegador Chrome. Esto ahora debería iniciar la app de Android TV en tu Android Receiver, y te permitirá controlar la reproducción con el control remoto de Android TV.
8. Felicitaciones
Ahora sabes cómo habilitar la transmisión de contenido en una app de video con los widgets del SDK de Cast en una app web de Chrome.
Para obtener más información, consulta la guía para desarrolladores de Web Sender.