Presentar las páginas web en pantallas secundarias adjuntas

Francisco Beaufort
François Beaufort

Chrome 66 permite que las páginas web usen una pantalla secundaria adjunta a través de la API de Presentación y controlen su contenido mediante la API de Presentation Receiver.

1/2. El usuario elige una pantalla secundaria adjunta
1/2. El usuario elige una pantalla secundaria adjunta
2/2. Se presenta automáticamente una página web en la pantalla seleccionada previamente.
2/2. Se presentará automáticamente una página web en la pantalla que se seleccionó anteriormente.

Información general

Hasta ahora, los desarrolladores web podían crear experiencias en las que un usuario veía contenido local en Chrome diferente del contenido que vería en una pantalla remota, a la vez que podía controlar esa experiencia de forma local. Algunos ejemplos incluyen administrar una cola de reproducción en youtube.com mientras se reproducen los videos en la TV o ver un corto de diapositivas con notas del orador en una laptop mientras la presentación en pantalla completa se muestra en una sesión de Hangouts.

Sin embargo, hay situaciones en las que los usuarios simplemente quieren presentar contenido en una segunda pantalla adjunta. Por ejemplo, imagina a un usuario en una sala de conferencias equipada con un proyector al que está conectado mediante un cable HDMI. En lugar de duplicar la presentación en un extremo remoto, el usuario realmente desea presentar las diapositivas en pantalla completa en el proyector y dejar la pantalla de la laptop disponible para las notas del orador y el control de las diapositivas. Si bien el autor del sitio puede respaldar esto de una manera muy rudimentaria (p.ej., abrir una ventana nueva, que el usuario debe arrastrar de forma manual a la pantalla secundaria y maximizarla a pantalla completa), es engorroso y proporciona una experiencia inconsistente entre la presentación local y la remota.

Cómo presentar una página

Permíteme explicarte cómo usar la API de Presentación para presentar una página web en la pantalla secundaria adjunta. El resultado final está disponible en https://googlechrome.github.io/samples/presentation-api/.

Primero, crearemos un nuevo objeto PresentationRequest que contendrá la URL que queremos presentar en la pantalla secundaria adjunta.

const presentationRequest = new PresentationRequest('receiver.html');

In this article, I won’t cover use cases where the parameter passed to
`PresentationRequest` can be an array like `['cast://foo’, 'apple://foo',
'https://example.com']` as this is not relevant there.

We can now monitor presentation display availability and toggle a "Present"
button visibility based on presentation displays availability. Note that we can
also decide to always show this button.

<aside class="caution"><b>Caution:</b> The browser may use more energy while the <code>availability</code> object is alive
and actively listening for presentation display availability changes. Please
use it with caution in order to save energy on mobile.</aside>

```js
presentationRequest.getAvailability()
  .then(availability => {
    console.log('Available presentation displays: ' + availability.value);
    availability.addEventListener('change', function() {
      console.log('> Available presentation displays: ' + availability.value);
    });
  })
  .catch(error => {
    console.log('Presentation availability not supported, ' + error.name + ': ' +
        error.message);
  });

Para mostrar un mensaje en una presentación, se requiere un gesto del usuario, como un clic en un botón. Entonces, llamemos a presentationRequest.start() con un clic en un botón y esperemos a que se resuelva la promesa una vez que el usuario seleccione una pantalla de presentación (p. ej., una pantalla secundaria adjunta en nuestro caso de uso).

function onPresentButtonClick() {
  presentationRequest.start()
  .then(connection => {
    console.log('Connected to ' + connection.url + ', id: ' + connection.id);
  })
  .catch(error => {
    console.log(error);
  });
}

La lista que se presenta al usuario también puede incluir extremos remotos, como dispositivos Chromecast, si estás conectado a una red que los anuncia. Ten en cuenta que las pantallas duplicadas no están en la lista. Consulta http://crbug.com/840466.

Selector de visualización de presentación
Selector de visualización de presentación

Cuando se resuelve la promesa, se presenta la página web en la URL del objeto PresentationRequest a la pantalla elegida. ¡Listo!

Ahora, podemos seguir explorando y supervisar los eventos "close" y "terminate", como se muestra a continuación. Ten en cuenta que es posible volver a conectarte a un presentationConnection "cerrado" con presentationRequest.reconnect(presentationId), en el que presentationId es el ID del objeto presentationRequest anterior.

function onCloseButtonClick() {
  // Disconnect presentation connection but will allow reconnection.
  presentationConnection.close();
}

presentationConnection.addEventListener('close', function() {
  console.log('Connection closed.');
});


function onTerminateButtonClick() {
  // Stop presentation connection for good.
  presentationConnection.terminate();
}

presentationConnection.addEventListener('terminate', function() {
  console.log('Connection terminated.');
});

Comunicarse con la página

Te preguntas, pero ¿cómo transfiero mensajes entre la página de mi controlador (la que acabamos de crear) y la página del receptor (la que pasamos al objeto PresentationRequest)?

Primero, recuperemos las conexiones existentes en la página del receptor con navigator.presentation.receiver.connectionList y escuchemos las conexiones entrantes como se muestra a continuación.

// Receiver page

navigator.presentation.receiver.connectionList
.then(list => {
  list.connections.map(connection => addConnection(connection));
  list.addEventListener('connectionavailable', function(event) {
    addConnection(event.connection);
  });
});

function addConnection(connection) {

  connection.addEventListener('message', function(event) {
    console.log('Message: ' + event.data);
    connection.send('Hey controller! I just received a message.');
  });

  connection.addEventListener('close', function(event) {
    console.log('Connection closed!', event.reason);
  });
}

Una conexión que recibe un mensaje activa un evento de "mensaje" que puedes escuchar. El mensaje puede ser una string, un BLOB, un ArrayBuffer o una ArrayBufferView. Para enviarlo, solo tienes que llamar a connection.send(message) desde la página del control o del receptor.

// Controller page

function onSendMessageButtonClick() {
  presentationConnection.send('Hello!');
}

presentationConnection.addEventListener('message', function(event) {
  console.log('I just received ' + event.data + ' from the receiver.');
});

Juega con la muestra en https://googlechrome.github.io/samples/presentation-api/ para tener una idea de cómo funciona. Estamos seguros de que disfrutarán este contenido tanto como yo.

Ejemplos y demostraciones

Echa un vistazo al ejemplo oficial de Chrome que usamos para este artículo.

También te recomiendo la demostración interactiva de Photowall. Esta app web permite que varios controladores presenten de forma colaborativa una presentación de diapositivas de fotos en una pantalla de presentación. El código está disponible en https://github.com/GoogleChromeLabs/presentation-api-samples.

Captura de pantalla de la demostración de Photowall
Foto de José Luis Mieza / CC BY-NC-SA 2.0

Una cosa más

Chrome tiene un menú del navegador “Transmitir” que los usuarios pueden invocar en cualquier momento mientras visitan un sitio web. Si deseas controlar la presentación predeterminada de este menú, asigna navigator.presentation.defaultRequest a un objeto presentationRequest personalizado que se creó antes.

// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;

Sugerencias para desarrolladores

Para inspeccionar y depurar la página del receptor, ve a la página chrome://inspect interna, selecciona "Otro" y haz clic en el vínculo "inspeccionar" junto a la URL que se presenta actualmente.

Inspeccionar las páginas del receptor de la presentación
Inspeccionar las páginas del receptor de presentación

También te recomendamos consultar la página interna de chrome://media-router-internals para explorar los procesos internos de descubrimiento y disponibilidad.

Próximos pasos

A partir de Chrome 66, se admiten las plataformas ChromeOS, Linux y Windows. La compatibilidad con Mac se incluirá más adelante.

Recursos