Aplikacja internetowa z obsługą przesyłania

1. Omówienie

Logo Google Cast

Dzięki tym ćwiczeniom w Codelabs dowiesz się, jak zmodyfikować istniejącą aplikację internetową do przesyłania 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. SDK Cast pozwala dodać niezbędne komponenty interfejsu zgodnie z listą kontrolną projektowania 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 utworzymy?

Po ukończeniu tego ćwiczenia w Codelabs masz do dyspozycji internetową aplikację wideo Chrome, która pozwala przesyłać filmy na urządzenie 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 przesyłającym i uruchomić odbiornik multimediów.
  • Jak przesyłać filmy.
  • Jak zintegrować Cast Connect

Czego potrzebujesz

  • Najnowsza przeglądarka Google Chrome
  • usługa hostingu HTTPS, np. Hosting Firebase czy 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

  • Niezbędna jest do tego wiedza o 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 ukończona 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 móc korzystać z ukończonych projektów, muszą one być hostowane.

Jeśli nie masz serwera do użycia, możesz skorzystać z Hostingu Firebase lub ngrok.

Uruchamianie serwera

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

Otwórz w przeglądarce adres URL HTTPS hostowanego fragmentu.

  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 wznowić odtwarzanie filmu.

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

Zanim przejdziemy dalej, zatrzymaj serwer.

4. Przygotowywanie projektu początkowego

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 nadawca działa na urządzeniu mobilnym lub laptopie,
  • aplikacja odbiornika na urządzeniu Google Cast).

Teraz możesz zacząć tworzyć projekt początkowy 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.

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

Projektowanie aplikacji

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

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

index.html

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

Jest kilka sekcji wyświetleń. Sekcja div#main_video zawiera element wideo. Z elementem div z filmem jest powiązany element div#media_control, który określa wszystkie elementy sterujące elementu 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. Spójrzmy na to.

CastVideos.js

Ten skrypt zarządza całą logiką aplikacji internetowej Cast. Lista filmów i powiązane z nimi metadane zdefiniowana w zasadzie CastVideos.js znajdują 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 multimedia i wybiera zdarzenia wiązania do PlayerHandler na potrzeby odtwarzania multimediów. CastPlayer.prototype.initializeCastPlayer to metoda konfigurowania wszystkich funkcji Cast. CastPlayer.prototype.switchPlayer przełącza stan między odtwarzaczem lokalnym a zdalnym. CastPlayer.prototype.setupLocalPlayer i CastPlayer.prototype.setupRemotePlayer inicjują odtwarzacz lokalny i zdalny.

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 tego przycisku wyświetla 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 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 przesyłającym lub jego rozłączenia na dowolnym ekranie aplikacji, co opisano na liście kontrolnej projektowania w 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 hostowana jest zawartość app-start.

Otwórz w przeglądarce adres URL hostowanej przez Ciebie próbki https.

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

Zdarzenie inicjujące

Platforma Cast ma globalny obiekt typu singleton – CastContext, który koordynuje wszystkie działania w ramach platformy. 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 polu CastPlayer.prototype.initializeCastPlayer ze wspomnianych wcześniej wywołań zwrotnych.

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

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 ten kod do polecenia index.html, aby zainicjować aplikację CastVideos oraz 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 polu CastVideos.js nową metodę. Odpowiada ona metodzie, którą właśnie wywołaliśmy w index.html. Dodajmy nową metodę o nazwie initializeCastPlayer, która ustawia opcje w CastContext i inicjuje nowe RemotePlayer oraz 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

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

Tak będzie wyglądać element przycisku:

<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. Po jego kliknięciu pojawi 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. 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

Rozszerzymy przykładową aplikację o możliwość zdalnego odtwarzania filmów na urządzeniu przesyłającym. 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 w pakiecie SDK Cast obiekt MediaInfo JSON, który modeluje element multimedialny.
  2. Użytkownik łączy się z urządzeniem przesyłającym, aby uruchomić aplikację odbiornika.
  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.

Etap 1 oznacza mapowanie jednego obiektu na drugi. MediaInfo to zrozumiały pakiet SDK Cast, a mediaJSON to kod elementu multimedialnego aplikacji. możemy łatwo zmapować mediaJSON na MediaInfo. Krok 2 w poprzedniej sekcji został już wykonany. Krok 3. Możesz łatwo wykonać krok 3 za pomocą pakietu Cast SDK.

Przykładowa aplikacja CastPlayer odróżnia odtwarzanie lokalne od zdalnego za pomocą 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 na podstawie przejść stanów, które mają miejsce w ramach platformy Cast. Jeśli na przykład rozpoczniemy przesyłanie, musimy zatrzymać odtwarzanie lokalne i wyłączyć niektóre elementy sterujące. Podobnie, jeśli zakończymy przesyłanie w tym kontrolerze widoku, będziemy musieli przełączyć się na odtwarzanie lokalne. Aby to uwzględnić, musimy nasłuchiwać różnych zdarzeń generowanych przez platformę Cast.

Zarządzanie sesją przesyłania

W przypadku platformy przesyłania sesja Cast obejmuje nawiązywanie połączenia z urządzeniem, uruchamianie (lub dołączanie do istniejącej sesji), nawiązywanie połączenia z aplikacją odbiornika oraz w razie potrzeby inicjowanie kanału sterowania multimediami. 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, klikając przycisk Cast, i zatrzymuje 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.

Sesje przesyłania zarządza aplikacja CastSession, do której można uzyskać dostęp w aplikacji 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 od konfiguracji Twojej aplikacji (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 rozwiązanie, więc zajmiemy się nim 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 CastSession, który obsługuje odtwarzanie multimediów, pakiet SDK będzie automatycznie tworzyć instancje RemotePlayer i RemotePlayerController. 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 trzeba wczytać wybrany film w odbiorniku, tworząc obiekt MediaInfo, który zostanie przetworzony i przekazany przez pakiet SDK. 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 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 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 : '');
  }
};

Teraz uruchom aplikację. Połącz się z urządzeniem przesyłającym 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 zgodność z odbiornikiem z Androidem

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. Identyfikator CredentialsData jest przekazywany do aplikacji na Androida TV tylko podczas uruchamiania lub dołączania do niej. Jeśli ustawisz je ponownie po nawiązaniu połączenia, nie zostanie ono przekazane do aplikacji na Androida TV.

Aby można było skonfigurować dane logowania do uruchomienia, trzeba zdefiniować pole CredentialsData w dowolnym momencie po ustawieniu opcji uruchamiania.

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 przy wczytywaniu żądania

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 zadbać o to, dodaj ten kod w polu 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 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.

Testuję Cast Connect

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

  1. Znajdź adres IP urządzenia z Androidem TV. Zwykle 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 folderu najwyższego poziomu z przykładowymi ćwiczeniami z programowania pobranymi na początku tego ćwiczenia. Na przykład:
$ cd Desktop/chrome_codelab_src
  1. Zainstaluj plik .apk z tego folderu w Androidzie TV, uruchamiając polecenie:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. Aplikacja Przesyłaj filmy powinna być teraz widoczna 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, klikając ikonę 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.