Aplikacja internetowa z obsługą przesyłania

1. Omówienie

Logo Google Cast

Z tego laboratorium programistycznego dowiesz się, jak zmodyfikować istniejącą aplikację do przesyłania filmów w internecie, aby przesyłać treści na urządzenie obsługujące Google Cast.

Co to jest Google Cast?

Google Cast umożliwia użytkownikom przesyłanie treści z urządzenia mobilnego na telewizor. Dzięki temu użytkownicy mogą używać swoich urządzeń mobilnych jako pilota do odtwarzania multimediów na telewizorze.

Pakiet Google Cast SDK umożliwia rozszerzenie aplikacji o sterowanie telewizorem lub systemem audio. Pakiet Cast SDK umożliwia dodawanie niezbędnych komponentów interfejsu użytkownika na podstawie listy kontrolnej dotyczącej interfejsu Google Cast.

Znajdziesz tam listę kontrolną projektowania Google Cast, która ułatwia i przewidywalność korzystania z Google Cast na wszystkich obsługiwanych platformach.

Co będziemy budować?

Po ukończeniu tego ćwiczenia będziesz mieć aplikację internetową do przesyłania filmów w Chrome, która umożliwia przesyłanie filmów na urządzenie z Google Cast.

Czego się nauczysz

  • Jak dodać pakiet Google Cast SDK do przykładowej aplikacji wideo.
  • Jak dodać przycisk przesyłania umożliwiający wybór urządzenia Google Cast?
  • Jak połączyć się z urządzeniem Cast i uruchomić odbiornik multimediów.
  • Jak przesyłać filmy.
  • Jak zintegrować Cast Connect

Czego potrzebujesz

  • najnowsza wersja przeglądarki Google Chrome,
  • usługa hostingu HTTPS, np. Hosting Firebase lub ngrok.
  • Urządzenie przesyłające Google Cast, takie jak Chromecast lub Android TV, skonfigurowane z dostępem do internetu.
  • telewizor lub monitor z wejściem HDMI.
  • Do testowania integracji Cast Connect wymagany jest Chromecast z Google TV, ale w pozostałych ćwiczeniach z programowania jest opcjonalny. Jeśli nie masz takiego urządzenia, możesz pominąć krok Dodaj obsługę Cast Connect pod koniec tego samouczka.

Doświadczenie

  • Musisz mieć już wcześniejsze doświadczenie w programowaniu stron internetowych.
  • Wymagamy też wcześniejszej wiedzy na temat oglądania telewizji. :)

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z tworzeniem aplikacji internetowych?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz swoje wrażenia z oglądania telewizji?

Początkujący Poziom średnio zaawansowany Biegły

2. Pobieranie przykładowego kodu

Możesz pobrać cały przykładowy kod na swój komputer...

i rozpakuj pobrany plik ZIP.

3. Uruchamianie przykładowej aplikacji

Logo Google Chrome

Najpierw zobaczmy, jak wygląda gotowa przykładowa aplikacja. Aplikacja jest podstawowym odtwarzaczem wideo. Użytkownik może wybrać film z listy i odtworzyć go lokalnie na urządzeniu lub przesłać na urządzenie przesyłające Google Cast.

Aby można było korzystać z ukończonego procesu, musi on być hostowany.

Jeśli nie masz serwera, możesz użyć hostingu Firebase lub ngrok.

Uruchamianie serwera

Po skonfigurowaniu wybranej usługi przejdź do app-done i uruchom serwer.

W przeglądarce otwórz adres URL https pliku hostowanego przez Ciebie.

  1. Powinna się wyświetlić aplikacja wideo.
  2. Kliknij przycisk Cast i wybierz urządzenie Google Cast.
  3. Wybierz film i kliknij przycisk odtwarzania.
  4. Rozpocznie się odtwarzanie filmu na urządzeniu Google Cast.

Obraz przedstawiający film odtwarzany na urządzeniu przesyłającym

Kliknij przycisk wstrzymania w elemencie wideo, aby wstrzymać odtwarzanie wideo na odbiorniku. Kliknij przycisk odtwarzania w elemencie wideo, aby ponownie odtworzyć film.

Kliknij przycisk Cast, by zatrzymać przesyłanie na urządzenie Google Cast.

Zanim przejdziemy dalej, zatrzymaj serwer.

4. Przygotowanie projektu startowego

Obraz przedstawiający film odtwarzany na urządzeniu przesyłającym

Musisz dodać obsługę Google Cast do pobranej przez Ciebie aplikacji startowej. Oto terminologia dotycząca Google Cast, której będziemy używać w tym ćwiczeniu z programowania:

  • aplikacja nadawcy działa na urządzeniu mobilnym lub laptopie,
  • aplikacja odbiornika na urządzeniu Google Cast).

Teraz możesz rozszerzyć projekt startowy za pomocą ulubionego edytora tekstu:

  1. Wybierz katalog ikona folderuapp-start z pobranego przykładowego kodu.
  2. Uruchom aplikację przy użyciu serwera i poznaj interfejs.

Podczas wykonywania ćwiczenia musisz ponownie umieścić na serwerze przykładowy kod w zależności od usługi.

Projektowanie aplikacji

Aplikacja pobiera listę filmów z zdalnego serwera internetowego i udostępnia ją użytkownikowi. Użytkownicy mogą wybrać film, aby wyświetlić jego szczegóły lub odtworzyć go lokalnie na urządzeniu mobilnym.

Aplikacja składa się z jednego głównego widoku zdefiniowanego w elementach index.html i głównego elementu sterującego CastVideos.js..

index.html

Ten plik HTML deklaruje prawie cały interfejs użytkownika aplikacji internetowej.

Jest kilka sekcji wyświetleń, mamy div#main_video, która zawiera element wideo. W przypadku elementu div wideo mamy element div#media_control, który definiuje wszystkie elementy sterujące elementem wideo. Pod spodem znajduje się ikona media_info, która zawiera szczegółowe informacje o oglądanym filmie. Na koniec element div carousel wyświetla listę filmów w elemencie div.

Plik index.html również wczytuje pakiet SDK Cast i informuje funkcję CastVideos, że ma się wczytać.

Większość treści, które będą wyświetlać się w tych elementach, jest zdefiniowana i wstrzykiwana oraz kontrolowana w CastVideos.js. Zobaczmy to.

CastVideos.js

Ten skrypt zarządza całą logiką aplikacji internetowej Cast Videos. Lista filmów i powiązanych z nimi metadanych zdefiniowanych w CastVideos.js znajduje się w obiekcie o nazwie mediaJSON.

Istnieje kilka głównych sekcji, które razem odpowiadają za zarządzanie filmami i ich odtwarzanie zarówno lokalnie, jak i zdalnie. Ogólnie jest to dość prosta aplikacja internetowa.

CastPlayer to główna klasa, która zarządza całą aplikacją, konfiguruje odtwarzacz, wybiera media i wiąże zdarzenia z PlayerHandler, aby odtwarzać media. CastPlayer.prototype.initializeCastPlayer to metoda konfigurowania wszystkich funkcji Cast. CastPlayer.prototype.switchPlayer przełącza stan między odtwarzaczami lokalnymi i zdalnymi. CastPlayer.prototype.setupLocalPlayerCastPlayer.prototype.setupRemotePlayer inicjują lokalnych i zdalnych graczy.

PlayerHandler to klasa odpowiedzialna za zarządzanie odtwarzaniem multimediów. Istnieje wiele innych metod związanych z zarządzaniem multimediami i odtwarzaniem.

Najczęstsze pytania

5. Dodawanie przycisku Cast

Obraz aplikacji obsługującej Cast

Aplikacja obsługująca Cast wyświetla w elemencie wideo przycisk Cast. Po kliknięciu przycisku przesyłania wyświetla się lista urządzeń przesyłania, które użytkownik może wybrać. Jeśli użytkownik odtwarzał treści lokalnie na urządzeniu nadawcy, wybranie urządzenia przesyłającego spowoduje uruchomienie lub wznowienie odtwarzania na tym urządzeniu. W dowolnym momencie sesji przesyłania użytkownik może kliknąć przycisk Cast i zatrzymać przesyłanie aplikacji na urządzenie przesyłające. Użytkownik musi mieć możliwość połączenia się z urządzeniem Cast lub odłączenia od niego na dowolnym ekranie aplikacji, zgodnie z opisem w spisie kontrolnym Google Cast Design.

Konfiguracja

Projekt początkowy wymaga tych samych zależności i konfiguracji co w przypadku ukończonej przykładowej aplikacji, ale tym razem hostowana jest zawartość app-start.

W przeglądarce otwórz adres URL https pliku hostowanego przez Ciebie.

Pamiętaj, że po wprowadzeniu zmian musisz ponownie umieścić próbkę na serwerze (w zależności od usługi).

Zdarzenie inicjujące

Platforma Cast ma globalny obiekt pojedynczy CastContext, który koordynuje wszystkie jej działania. Ten obiekt musi zostać zainicjowany na wczesnym etapie cyklu życia aplikacji. Zwykle jest to wywołanie zwrotne przypisane do window['__onGCastApiAvailable'], które jest wywoływane po wczytaniu pakietu Cast SDK i gotowe do użycia. W tym przypadku funkcja CastContext jest wywoływana w funkcji CastPlayer.prototype.initializeCastPlayer, która jest wywoływana z wymienionego wcześniej wywołania zwrotnego.

Podczas inicjowania CastContext musisz podać obiekt JSON options. Ta klasa zawiera opcje, które mają wpływ na działanie platformy. Najważniejszym z nich jest identyfikator aplikacji odbiorczej, który służy do filtrowania listy dostępnych urządzeń Cast, aby wyświetlać tylko urządzenia, na których można uruchomić określoną aplikację, oraz do uruchamiania aplikacji odbiorczej po rozpoczęciu sesji Cast.

Gdy tworzysz własną aplikację obsługującą Google Cast, musisz zarejestrować się jako programista Cast, a potem uzyskać dla niej identyfikator. W tym ćwiczeniu z programowania użyjemy przykładowego identyfikatora aplikacji.

Dodaj ten kod do index.html na samym końcu sekcji body:

<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

Dodaj do pliku index.html ten kod, aby zainicjować aplikację CastVideos i zainicjować CastContext:

<script src="CastVideos.js"></script>
<script type="text/javascript">
var castPlayer = new CastPlayer();
window['__onGCastApiAvailable'] = function(isAvailable) {
  if (isAvailable) {
    castPlayer.initializeCastPlayer();
  }
};
</script>

Teraz musimy dodać w funkcji CastVideos.js nową metodę odpowiadającą metodzie wywołanej w funkcji index.html. Dodajmy nową metodę o nazwie initializeCastPlayer, która ustawia opcje w CastContext i inicjalizuje nowe obiekty RemotePlayerRemotePlayerControllers:

/**
 * 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)
    );
};

Na koniec musimy utworzyć zmienne dla RemotePlayer i RemotePlayerController:

var CastPlayer = function() {
  //...
  /* Cast player variables */
  /** @type {cast.framework.RemotePlayer} */
  this.remotePlayer = null;
  /** @type {cast.framework.RemotePlayerController} */
  this.remotePlayerController = null;
  //...
};

Przycisk Cast

Urządzenie CastContext jest już zainicjowane. Teraz trzeba dodać przycisk Cast, aby użytkownik mógł wybrać urządzenie przesyłające. Pakiet SDK Cast udostępnia komponent przycisku Cast o nazwie google-cast-launcher z identyfikatorem „castbutton"”. Można go dodać do elementu wideo aplikacji, dodając element button w sekcji media_control.

Element przycisku będzie wyglądał tak:

<google-cast-launcher id="castbutton"></google-cast-launcher>

Dodaj do index.html w sekcji media_control ten kod:

<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>

Teraz odśwież stronę w przeglądarce Chrome. W elemencie wideo powinien pojawić się przycisk Cast. Po jego kliknięciu zobaczysz listę urządzeń Cast w sieci lokalnej. Wykrywaniem urządzeń zarządza automatycznie przeglądarka Chrome. Wybierz urządzenie przesyłające. Aplikacja odbiornika załaduje się na to urządzenie.

Nie wprowadziliśmy jeszcze obsługi odtwarzania multimediów, więc na razie nie możesz odtwarzać filmów na urządzeniu Cast. Kliknij przycisk Cast, by zatrzymać przesyłanie.

6. Przesyłanie treści wideo

Obraz aplikacji obsługującej Cast z menu wyboru urządzenia przesyłającego

Rozwiniemy przykładową aplikację, aby można było odtwarzać filmy zdalnie na urządzeniu obsługującym Cast. Aby to zrobić, musisz nasłuchiwać różnych zdarzeń generowanych przez platformę Cast.

Przesyłanie multimediów

Ogólnie rzecz biorąc, jeśli chcesz odtworzyć multimedia na urządzeniu przesyłającym, musisz spełnić te warunki:

  1. Utwórz obiekt MediaInfo JSON z pakietu SDK Google Cast, który modeluje element multimedialny.
  2. Użytkownik łączy się z urządzeniem Cast, aby uruchomić aplikację odbiorczą.
  3. Wczytaj obiekt MediaInfo do odbiornika i odtwórz treści.
  4. Śledź stan multimediów.
  5. Wysyłaj polecenia odtwarzania do odbiornika na podstawie interakcji użytkownika.

Krok 1 polega na mapowaniu jednego obiektu na inny. MediaInfo jest obiektem zrozumiałym dla pakietu Cast SDK, a mediaJSON jest elementem multimedialnym zakapsułowanym w naszej aplikacji. Możemy łatwo mapować mediaJSON na MediaInfo. Krok 2 został już wykonany w poprzedniej sekcji. Krok 3. Możesz łatwo wykonać krok 3 za pomocą pakietu Cast SDK.

Przykładowa aplikacja CastPlayer już rozróżnia odtwarzanie lokalne i zdalne w ramach metody switchPlayer:

if (cast && cast.framework) {
  if (this.remotePlayer.isConnected) {
    //...

Z tego ćwiczenia z programowania nie musisz dokładnie wiedzieć, jak działa przykładowa logika odtwarzacza. Warto jednak pamiętać, że trzeba zmodyfikować odtwarzacz multimediów w aplikacji, aby uwzględniał zarówno odtwarzanie lokalne, jak i zdalne.

W tej chwili lokalny odtwarzacz jest zawsze w lokalnym stanie odtwarzania, bo nie wie jeszcze nic o stanach przesyłania. Musimy zaktualizować interfejs użytkownika na podstawie przejść między stanami, które występują w ramach platformy Cast. Jeśli na przykład zaczniemy przesyłać treści, musimy zatrzymać odtwarzanie na urządzeniu lokalnym i wyłączyć niektóre elementy sterujące. Podobnie, jeśli przestaniemy przesyłać strumieniowo, gdy jesteśmy w tym kontrolerze widoku, musimy przejść do odtwarzania lokalnego. Aby to uwzględnić, musimy nasłuchiwać różnych zdarzeń generowanych przez platformę Cast.

Zarządzanie sesją przesyłania

W ramach platformy Cast sesja Cast łączy w sobie czynności polegające na połączeniu z urządzeniem, uruchomieniu (lub dołączeniu do istniejącej sesji), połączeniu z aplikacją odbiorczą i inicjowaniu kanału sterowania multimediami (w odpowiednich przypadkach). Kanał sterowania multimediami to sposób, w jaki platforma Cast wysyła i odbiera od odbiornika komunikaty dotyczące odtwarzania multimediów.

Sesja przesyłania rozpocznie się automatycznie, gdy użytkownik wybierze urządzenie za pomocą przycisku przesyłania, i zatrzyma się automatycznie, gdy użytkownik się rozłączy. Ponowne łączenie z sesją odbiornika z powodu problemów z siecią jest również automatycznie obsługiwane przez platformę Cast.

Sesjami przesyłania steruje CastSession, do której można uzyskać dostęp przez cast.framework.CastContext.getInstance().getCurrentSession(). Wywołania zwrotne EventListener mogą służyć do monitorowania zdarzeń sesji, takich jak utworzenie, zawieszenie, wznowienie i zakończenie.

W naszej obecnej aplikacji wszystkie zarządzanie sesjami i stanami są obsługiwane za pomocą metody setupRemotePlayer. Zacznijmy konfigurowanie w aplikacji. Dodaj do niej ten kod: 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();
};

Nadal musimy powiązać wszystkie zdarzenia z wywołań zwrotnych i obsługiwać wszystkie przychodzące zdarzenia. To dość proste, więc zajmijmy się tym teraz:

/**
 * 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();
};

Wczytywanie multimediów

W pakiecie Cast SDK interfejsy RemotePlayerRemotePlayerController zapewniają zestaw wygodnych interfejsów API do zdalnego zarządzania odtwarzaniem multimediów na odbiorniku. W przypadku CastSession, który obsługuje odtwarzanie multimediów, pakiety RemotePlayerRemotePlayerController zostaną utworzone automatycznie przez pakiet SDK. Aby uzyskać do nich dostęp, utwórz instancje odpowiednio cast.framework.RemotePlayer i cast.framework.RemotePlayerController, jak pokazano to wcześniej w ćwiczeniach z programowania.

Następnie musimy załadować wybrany obecnie film na odbiorniku, tworząc obiekt MediaInfo, który pakiet SDK przetworzy i przekaże w ramach żądania. Aby to zrobić, dodaj do setupRemotePlayer ten kod:

/**
 * 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);

    //...
};

Teraz dodaj metodę przełączania się między odtwarzaniem lokalnym i zdalnym:

/**
 * 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();
};

Na koniec dodaj metodę obsługi wszelkich komunikatów o błędach 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 : '');
  }
};

Uruchom aplikację, połącz się z urządzeniem z Cast i zacznij odtwarzać film. Film powinien być odtwarzany na odbiorniku.

7. Dodaj obsługę Cast Connect

Biblioteka Cast Connect pozwala dotychczasowym aplikacjom nadawcy komunikować się z aplikacjami na Androida TV przy użyciu protokołu Cast. Cast Connect opiera się na infrastrukturze Cast, a aplikacja na Androida TV jest odbiornikiem.

Zależności

  • przeglądarka Chrome w wersji M87 lub nowszej,

Ustaw Android Receiver Compatible

Aby uruchomić aplikację na Androida TV (znaną też jako odbiornik Androida), w obiekcie CastOptions trzeba ustawić flagę androidReceiverCompatible na „true”.

Dodaj ten kod do pola CastVideos.js w funkcji initializeCastPlayer:

var options = {};
...
options.androidReceiverCompatible = true;

cast.framework.CastContext.getInstance().setOptions(options);

Ustaw dane logowania do uruchamiania

Po stronie nadawcy możesz określić, kto dołącza do sesji, określając CredentialsData. credentials to ciąg znaków, który może być zdefiniowany przez użytkownika, o ile tylko aplikacja ATV go rozumie. Wartość CredentialsData jest przekazywana do aplikacji na Androida TV tylko podczas uruchamiania lub dołączania. Jeśli ustawisz je ponownie po nawiązaniu połączenia, nie zostanie ono przekazane do aplikacji na Androida TV.

Aby skonfigurować opcje logowania CredentialsData, musisz je zdefiniować w dowolnym momencie po skonfigurowaniu opcji uruchamiania.

Dodaj do klasy CastVideos.js w ramach funkcji initializeCastPlayer ten kod:

cast.framework.CastContext.getInstance().setOptions(options);
...
let credentialsData = new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);
...

Ustawianie danych logowania w żądaniu wczytania

Jeśli aplikacja odbiornika internetowego i aplikacja na Androida TV obsługuje credentials w inny sposób, konieczne może być zdefiniowanie osobnych danych logowania dla każdego z nich. Aby to zrobić, dodaj ten kod w funkcji CastVideos.js w ramach funkcji playerTarget.load:

...
var request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

W zależności od aplikacji odbiornika, do której nadawca przesyła treści, pakiet SDK będzie teraz automatycznie obsługiwać dane uwierzytelniające, których chcesz użyć w bieżącej sesji.

Testowanie Cast Connect

Aby zainstalować plik APK Androida TV na urządzeniu Chromecast z Google TV:

  1. Znajdź adres IP urządzenia z Androidem TV. Zazwyczaj ta opcja jest dostępna w sekcji Ustawienia > Sieć i Internet > Nazwa sieci, z którą połączone jest urządzenie. Po prawej stronie pojawią się szczegóły oraz adres IP urządzenia w sieci.
  2. Użyj adresu IP, by połączyć się z urządzeniem przez ADB:
$ adb connect <device_ip_address>:5555
  1. W oknie terminala przejdź do najwyższego poziomu folderu przykładów kodu pobranego na początku tego ćwiczenia. Na przykład:
$ cd Desktop/chrome_codelab_src
  1. Zainstaluj plik .apk w tym folderze na Androidzie TV, uruchamiając:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Na urządzeniu z Androidem TV w menu Twoje aplikacje powinieneś teraz zobaczyć aplikację o nazwie Przesyłaj filmy.
  2. Uruchom zaktualizowany kod nadawcy i rozpocznij sesję przesyłania na urządzeniu z Androidem TV, korzystając z ikony przesyłania lub wybierając Cast.. z menu w przeglądarce Chrome. Powinno teraz uruchomić się aplikacja Android TV na odbiorniku z Androidem i umożliwić sterowanie odtwarzaniem za pomocą pilota Android TV.

8. Gratulacje

Wiesz już, jak włączyć przesyłanie dla aplikacji wideo, korzystając z widżetów Cast SDK w aplikacji internetowej Chrome.

Więcej informacji znajdziesz w przewodniku dla programistów Web Sender.