Aplikacja internetowa z obsługą przesyłania

1. Opis

Logo Google Cast

Dzięki tym ćwiczeniom z programowania dowiesz się, jak zmodyfikować istniejącą aplikację internetową, by przesyłać treści na urządzenie obsługujące Google Cast.

Co to jest Google Cast?

Google Cast pozwala użytkownikom przesyłać 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 SDK Google Cast pozwala rozszerzyć aplikację o sterowanie telewizorem lub systemem audio. Pakiet SDK Cast pozwala dodać niezbędne komponenty interfejsu zgodnie z listą kontrolną projektowania Google Cast.

Dostępna jest lista kontrolna projektu Google Cast, dzięki której korzystanie z Cast jest proste i przewidywalne na wszystkich obsługiwanych platformach.

Co będziemy tworzyć?

Po ukończeniu tych ćwiczeń z programowania będziesz mieć internetową aplikację wideo Chrome, która będzie mogła przesyłać filmy na urządzenie Google Cast.

Czego się nauczysz

  • Jak dodać pakiet SDK Google Cast do przykładowej aplikacji wideo
  • Jak dodać przycisk Cast pozwalający wybrać urządzenie Google Cast.
  • Jak połączyć się z urządzeniem przesyłającym i uruchomić odbiornik multimediów.
  • Jak przesłać film.
  • Jak zintegrować Cast Connect

Czego potrzebujesz

  • najnowszą przeglądarkę Google Chrome,
  • usługa hostingu HTTPS, na przykład Firebase Hosting lub ngrok;
  • Urządzenie przesyłające Google Cast, takie jak Chromecast czy Android TV, 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łej części Codelabs jest on opcjonalny. Jeśli go nie masz, możesz pominąć krok Dodawanie obsługi Cast Connect pod koniec tego samouczka.

Funkcja

  • Aby skorzystać z tej możliwości, musisz mieć wiedzę w zakresie tworzenia stron internetowych.
  • Potrzebna będzie też wcześniejsza wiedza o oglądaniu telewizji :)

Jak będziesz korzystać z tego samouczka?

Przeczytaj tylko do końca Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z tworzeniem aplikacji internetowych?

Początkujący Średni Średni

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

Początkujący Średni Średni

2. Pobieranie przykładowego kodu

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

i rozpakuj pobrany plik ZIP.

3. Uruchamianie przykładowej aplikacji

Logo Google Chrome

Zobaczmy najpierw, jak wygląda kompletna przykładowa aplikacja. Ta aplikacja to podstawowy odtwarzacz wideo. Użytkownik może wybrać film z listy, a potem odtworzyć go lokalnie na urządzeniu lub przesłać na urządzenie przesyłające Google Cast.

Aby można było używać ukończonych zadań, musi być hostowany.

Jeśli nie masz serwera, którego można użyć, 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 hostowanego przykładu.

  1. Powinna pojawić się 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 filmu odtwarzanego na urządzeniu przesyłającym

Kliknij przycisk wstrzymania w elemencie wideo, aby wstrzymać odtwarzanie filmu na odbiorniku. Kliknij przycisk odtwarzania w elemencie wideo, aby wznowić odtwarzanie filmu.

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

Zanim przejdziemy dalej, zatrzymaj serwer.

4. Przygotuj projekt początkowy

Obraz filmu odtwarzanego na urządzeniu przesyłającym

Musimy dodać obsługę Google Cast do pobranej aplikacji startowej. Oto niektóre z terminologii związanej z Google Cast, których będziemy używać w tym ćwiczeniu z programowania:

  • aplikacja nadawca działa na urządzeniu mobilnym lub laptopie,
  • aplikacja odbiornika działa na urządzeniu Google Cast;

Możesz teraz zacząć pracować nad projektem początkowym 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 użytkownika.

Uwaga: w trakcie tych ćwiczeń z programowania konieczne będzie ponowne hostowanie przykładowego kodu na serwerze, w zależności od usługi.

Projektowanie aplikacji

Aplikacja pobiera listę filmów ze zdalnego serwera WWW i udostępnia listę, którą użytkownik może przeglądać. Użytkownicy mogą wybrać film, aby zobaczyć szczegóły, lub odtworzyć go lokalnie na urządzeniu mobilnym.

Aplikacja składa się z 1 widoku głównego zdefiniowanego w aplikacji index.html oraz z kontrolera głównego CastVideos.js.

index.html

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

Jest kilka sekcji wyświetleń, czyli element div#main_video, który zawiera element wideo. Z elementem div elementu wideo jest też powiązany element div#media_control, który określa wszystkie elementy sterujące elementu wideo. Poniżej znajduje się opcja media_info, która zawiera szczegóły wyświetlonego filmu. Element div carousel wyświetla listę filmów w elemencie div.

Plik index.html również uruchamia pakiet SDK Cast i informuje funkcję CastVideos, by została załadowana.

Większość treści, które wypełnią te elementy, jest definiowana, wstrzykiwana i kontrolowana w narzędziu CastVideos.js. Przyjrzyjmy się temu.

CastVideos.js

Ten skrypt zarządza wszystkimi działaniami logicznymi aplikacji internetowej przesyłania filmów. Lista filmów i powiązane z nimi metadane zdefiniowane w zasadzie CastVideos.js znajdują się w obiekcie o nazwie mediaJSON.

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

CastPlayer to klasa główna, która zarządza całą aplikacją, konfigurując odtwarzacz, wybierając multimedia i wiążąc zdarzenia z PlayerHandler na potrzeby odtwarzania multimediów. CastPlayer.prototype.initializeCastPlayer to metoda, która konfiguruje wszystkie funkcje przesyłania. CastPlayer.prototype.switchPlayer przełącza stan między odtwarzaczem lokalnym a zdalnym. CastPlayer.prototype.setupLocalPlayer i CastPlayer.prototype.setupRemotePlayer inicjują odtwarzacze lokalne i zdalne.

Klasa PlayerHandler jest odpowiedzialna za zarządzanie odtwarzaniem multimediów. Istnieje wiele innych metod, które odpowiadają za szczegółowe informacje o zarządzaniu multimediami i odtwarzaniem.

Najczęstsze pytania

5. Dodawanie przycisku Cast

Obraz aplikacji obsługującej Cast

Aplikacja obsługująca Cast wyświetla przycisk Cast w elemencie wideo. Gdy klikniesz przycisk Cast, pojawi się lista urządzeń przesyłających, 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 rozpocznie lub wznowi odtwarzanie na tym urządzeniu. W każdej chwili podczas 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 przesyłającym lub ich odłączenia na dowolnym ekranie aplikacji zgodnie z opisem na liście kontrolnej projektowania Google Cast.

Konfiguracja

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

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

Pamiętaj, że po wprowadzeniu zmian konieczne będzie ponowne przechowywanie próbki na serwerze w zależności od usługi.

Zdarzenie inicjujące

Platforma przesyłania zawiera globalny obiekt typu singleton CastContext, który koordynuje wszystkie działania platformy. Obiekt musi zostać zainicjowany na wczesnym etapie cyklu życia aplikacji. Zwykle jest on wywoływany z wywołania zwrotnego przypisanego do window['__onGCastApiAvailable'], które jest wywoływane po wczytaniu pakietu SDK Cast i jest dostępny do użycia. W tym przypadku CastContext nosi nazwę CastPlayer.prototype.initializeCastPlayer, która jest wywoływana ze wspomnianego wcześniej wywołania zwrotnego.

Podczas inicjowania CastContext należy podać obiekt JSON options. Ta klasa zawiera opcje, które wpływają na działanie platformy. Najważniejszy z nich jest identyfikator aplikacji odbiorcy, który służy do filtrowania listy dostępnych urządzeń przesyłających w celu wyświetlenia tylko tych, które mogą uruchomić określoną aplikację i uruchamiania tej aplikacji po rozpoczęciu sesji przesyłania.

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

Dodaj do index.html ten kod 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 oraz 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 metodzie CastVideos.js nową metodę, która odpowiada metodzie, którą właśnie wywołaliśmy w funkcji index.html. Dodajmy nową metodę o nazwie initializeCastPlayer, która ustawia opcje w CastContext i inicjuje nowe RemotePlayer i 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)
    );
};

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

Po zainicjowaniu CastContext musimy dodać przycisk Cast, by umożliwić użytkownikowi wybranie urządzenia przesyłającego. Pakiet SDK Cast udostępnia komponent przycisku przesyłania o nazwie google-cast-launcher o identyfikatorze „castbutton"”. Można go dodać do elementu wideo aplikacji, dodając po prostu button w sekcji media_control.

Tak będzie wyglądać przycisk:

<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 być widoczny przycisk Cast, a po jego kliknięciu wyświetli się lista urządzeń przesyłających w Twojej sieci lokalnej. Wykrywaniem urządzeń zarządza automatycznie przeglądarka Chrome. Wybierz urządzenie przesyłające, a przykładowa aplikacja odbiornika zostanie na nim załadowana.

Nie obsługujemy jeszcze odtwarzania multimediów, więc nie możesz jeszcze odtwarzać filmów na urządzeniu przesyłającym. 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

Udostępnimy przykładową aplikację, aby umożliwić zdalne odtwarzanie filmów na urządzeniach przesyłających. Aby to zrobić, musimy wsłuchiwać się w różne zdarzenia generowane przez platformę przesyłania.

Przesyłanie multimediów

Ogólnie, jeśli chcesz odtworzyć multimedia na urządzeniu przesyłającym, musisz wykonać te czynności:

  1. Korzystając z pakietu SDK Cast, utwórz obiekt MediaInfo JSON, który będzie modelował element multimedialny.
  2. Użytkownik łączy się z urządzeniem przesyłającym, by uruchomić aplikację odbiornika.
  3. Wczytaj obiekt MediaInfo do odbiornika i odtwórz treści.
  4. Śledzenie stanu multimediów.
  5. Wysyłaj polecenia odtwarzania do odbiornika na podstawie interakcji użytkownika.

Krok 1 polega na zmapowaniu jednego obiektu na drugi. Pakiet MediaInfo jest zrozumiały dla pakietu SDK Cast, a mediaJSON to kodowanie elementu multimedialnego w naszej aplikacji. Możemy z łatwością zmapować obiekt mediaJSON na obiekt MediaInfo. Krok 2 z poprzedniej sekcji został już wykonany. Krok 3 można łatwo zrobić za pomocą pakietu SDK Cast.

Przykładowa aplikacja CastPlayer odróżnia już w metodzie switchPlayer odtwarzanie lokalne od zdalnego:

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

W tym ćwiczeniu z programowania nie ma potrzeby dokładnego zrozumienia, jak działa cała przykładowa logika odtwarzacza. Pamiętaj jednak, że musisz zmodyfikować odtwarzacz w aplikacji, aby mieć możliwość odtwarzania zarówno lokalnego, jak i zdalnego.

W tej chwili lokalny odtwarzacz jest zawsze w lokalnym stanie odtwarzania, ponieważ nie ma jeszcze żadnych informacji o stanach przesyłania. Musimy aktualizować interfejs odpowiednio do zmian stanu w platformie przesyłania. Jeśli na przykład rozpocznie się przesyłanie, musimy zatrzymać odtwarzanie lokalne i wyłączyć niektóre elementy sterujące. Podobnie jeśli zatrzymujemy przesyłanie, gdy korzystamy z kontrolera widoku, musimy przejść na odtwarzanie lokalne. Aby to zrobić, musimy nasłuchiwać różnych zdarzeń generowanych przez platformę przesyłania.

Zarządzanie sesjami przesyłania

W przypadku platformy przesyłania sesja przesyłania składa się z etapów połączenia z urządzeniem, uruchomienia (lub dołączenia do istniejącej sesji), połączenia z aplikacją odbiornika i (w razie potrzeby) zainicjowania kanału sterowania multimediami. Kanał sterowania multimediami to sposób, w jaki platforma przesyłania wysyła i odbiera komunikaty dotyczące odtwarzania multimediów z odbiornika.

Sesja przesyłania rozpocznie się automatycznie, gdy użytkownik wybierze urządzenie, klikając przycisk Cast, i zakończy się automatycznie, gdy użytkownik rozłączy się. Ponowne łączenie z sesją odbiorcy z powodu problemów z siecią jest również automatycznie obsługiwane przez platformę przesyłania.

Sesje przesyłania są zarządzane przez narzędzie CastSession, do którego można uzyskać dostęp przez aplikację 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 sesji.

W naszej obecnej aplikacji zarządzanie wszystkimi sesjami i stanami odbywa się za nas przy użyciu metody setupRemotePlayer. Zacznijmy konfigurować tę funkcję w Twojej aplikacji, dodając do CastVideos.js ten kod:

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

Wczytuję multimedia

RemotePlayer i RemotePlayerController w pakiecie SDK Cast zapewniają zestaw wygodnych interfejsów API do zarządzania zdalnym odtwarzaniem multimediów na odbiorniku. W przypadku pakietu CastSession, który obsługuje odtwarzanie multimediów, pakiet SDK utworzy automatycznie wystąpienia elementów RemotePlayer i RemotePlayerController. Aby uzyskać do nich dostęp, utwórz instancje odpowiednio cast.framework.RemotePlayer i cast.framework.RemotePlayerController, jak pokazano wcześniej w ćwiczeniach z programowania.

Następnie musimy wczytać aktualnie wybrany film na odbiorniku, tworząc obiekt MediaInfo, aby pakiet SDK mógł przetworzyć i przekazać żądanie. Aby to zrobić, dodaj ten kod do pliku 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);

    //...
};

Teraz dodaj metodę przełączania między odtwarzaniem lokalnym a 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 przesyłania:

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

Teraz uruchom aplikację. Połącz się z urządzeniem przesyłającym i zacznij odtwarzać film. Film powinien być odtwarzany na odbiorniku.

7. Dodawanie obsługi Cast Connect

Biblioteka Cast Connect umożliwia dotychczasowym aplikacjom nadawcy komunikację z aplikacjami na Androida TV przez protokół Cast. Cast Connect działa na bazie infrastruktury przesyłania, a aplikacja na Androida TV działa jako odbiornik.

Zależności

  • Przeglądarka Chrome w wersji M87 lub nowszej

Ustaw zgodność odbiornika z Androidem

Aby uruchomić aplikację Android TV (określaną też jako odbiornik Androida), musimy ustawić w obiekcie CastOptions flagę androidReceiverCompatible na true.

Dodaj ten kod do elementu 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ć CredentialsData, aby reprezentował, kto dołącza do sesji. Ciąg credentials jest ciągiem zdefiniowanym przez użytkownika, pod warunkiem że jest on zrozumiały dla aplikacji ATV. Element CredentialsData jest przekazywany do aplikacji na Androida TV tylko w czasie jej uruchomienia lub dołączenia. Jeśli skonfigurujesz je ponownie po połączeniu z siecią, nie zostaną one przekazane do aplikacji na Androida TV.

Aby skonfigurować dane logowania do uruchamiania, w każdej chwili po ustawieniu opcji uruchamiania musi być zdefiniowany CredentialsData.

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

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

Ustaw dane logowania w żądaniu obciążenia

Jeśli aplikacja Web Recipient i aplikacja na Androida TV obsługują credentials inaczej, konieczne może być zdefiniowanie osobnych danych logowania do każdej z nich. Aby się tym zająć, dodaj ten kod do elementu CastVideos.js w polu playerTarget.load w funkcji setupRemotePlayer:

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

W zależności od aplikacji odbiorcy, do której nadawca przesyła treści, pakiet SDK automatycznie określa dane logowania, których będzie używać w bieżącej sesji.

Testowanie Cast Connect

Instalowanie pakietu APK na Androida TV na urządzeniu Chromecast z Google TV:

  1. Znajdź adres IP swojego urządzenia z Androidem TV. Zwykle znajdziesz je w sekcji Ustawienia > Sieć i internet > (nazwa sieci, z którą połączone jest urządzenie). Po prawej stronie wyświetlą się szczegóły oraz adres IP urządzenia połączony z siecią.
  2. Użyj adresu IP urządzenia, aby połączyć się z nim przez ADB za pomocą terminala:
$ adb connect <device_ip_address>:5555
  1. W oknie terminala przejdź do folderu najwyższego poziomu na przykłady ćwiczeń z programowania pobrane na początku tego ćwiczenia z programowania. Na przykład:
$ cd Desktop/chrome_codelab_src
  1. Zainstaluj plik .apk w tym folderze na Androidzie TV, uruchamiając polecenie:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Aplikacja powinna być teraz widoczna pod nazwą Przesyłaj filmy w menu Twoje aplikacje na urządzeniu z Androidem TV.
  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 to spowodować uruchomienie aplikacji Android TV na odbiorniku Android TV i umożliwienie sterowania odtwarzaniem za pomocą pilota Android TV.

8. Gratulacje

Wiesz już, jak włączyć przesyłanie w aplikacji wideo za pomocą widżetów pakietu SDK Cast w aplikacji internetowej Chrome.

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