Dodaj podstawowe funkcje do niestandardowego odbiornika internetowego

Ta strona zawiera fragmenty kodu i opisy funkcji dostępnych dla niestandardowego odbiornika internetowego.

  1. Element cast-media-player reprezentujący wbudowany interfejs odtwarzacza dostarczany z odbiornikiem internetowym.
  2. Niestandardowe style przypominające CSS dla elementu cast-media-player, umożliwiające stylizowanie różnych elementów interfejsu, takich jak background-image, splash-image i font-family.
  3. Element skryptu służący do wczytywania platformy Web Receivedr.
  4. Kod JavaScript do przechwytywania wiadomości i obsługi zdarzeń.
  5. Kolejka do autoodtwarzania.
  6. Opcje konfigurowania odtwarzania.
  7. Opcje ustawiania kontekstu odbiornika internetowego.
  8. Opcje ustawiania poleceń obsługiwanych przez aplikację Web Receivedr.
  9. Wywołanie JavaScriptu uruchamiającego aplikację Web Odbiornik.

Konfiguracja i opcje aplikacji

Konfigurowanie aplikacji

CastReceiverContext to najbardziej zewnętrzna klasa widoczna dla dewelopera, która zarządza wczytywaniem bazowych bibliotek i obsługuje inicjowanie pakietu Web pickupr SDK. Pakiet SDK udostępnia interfejsy API, które pozwalają deweloperom aplikacji na jego konfigurowanie za pomocą CastReceiverOptions. Te konfiguracje są oceniane raz przy każdym uruchomieniu aplikacji i są przekazywane do pakietu SDK podczas ustawiania opcjonalnego parametru w wywołaniu start.

Poniższy przykład pokazuje, jak zastąpić domyślne działanie związane z wykrywaniem, czy połączenie z nadawcą jest nadal aktywne. Gdy odbiornik internetowy nie może skomunikować się z nadawcą przez maxInactivity sekund, wysyłane jest zdarzenie SENDER_DISCONNECTED. Poniższa konfiguracja zastępuje ten limit czasu. Może to być przydatne podczas debugowania problemów, ponieważ zapobiega zamknięciu sesji zdalnego debugowania Chrome przez aplikację Web Received, gdy nie ma żadnych połączonych nadawców w stanie IDLE.

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

Skonfiguruj odtwarzacz

Podczas wczytywania treści pakiet Web pickupr SDK umożliwia konfigurowanie zmiennych odtwarzania, takich jak informacje o DRM, ponowne próby konfiguracji oraz moduły obsługi żądań za pomocą cast.framework.PlaybackConfig. Te informacje są obsługiwane przez PlayerManager i są oceniane podczas tworzenia odtwarzaczy. Odtwarzacze są tworzone za każdym razem, gdy nowe wczytanie jest przekazywane do pakietu Web Recipientr SDK. Zmiany wprowadzone w elemencie PlaybackConfig po utworzeniu odtwarzacza są sprawdzane przy następnym wczytaniu treści. Pakiet SDK udostępnia te metody modyfikowania PlaybackConfig.

  • CastReceiverOptions.playbackConfig, aby zastąpić domyślne opcje konfiguracji podczas inicjowania CastReceiverContext.
  • PlayerManager.getPlaybackConfig(), aby uzyskać bieżącą konfigurację.
  • PlayerManager.setPlaybackConfig(), aby zastąpić bieżącą konfigurację. To ustawienie będzie stosowane do wszystkich kolejnych operacji wczytywania lub do czasu jego ponownego zastąpienia.
  • PlayerManager.setMediaPlaybackInfoHandler(), aby zastosować dodatkowe konfiguracje tylko do elementu multimedialnego wczytywanego na podstawie obecnych konfiguracji. Moduł obsługi jest wywoływany tuż przed utworzeniem odtwarzacza. Wprowadzone tu zmiany nie są trwałe i nie są uwzględniane w zapytaniach do getPlaybackConfig(). Po wczytaniu następnego elementu multimedialnego ten moduł obsługi jest wywoływany ponownie.

Przykład poniżej pokazuje, jak ustawić PlaybackConfig podczas inicjowania CastReceiverContext. Zastępuje ona wychodzące żądania uzyskiwania plików manifestu. Moduł obsługi określa, że żądania kontroli dostępu CORS powinny być wykonywane za pomocą danych logowania, takich jak pliki cookie lub nagłówki autoryzacji.

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

Poniższy przykład pokazuje, jak zastąpić parametr PlaybackConfig za pomocą metody getter i seter dostępnych w PlayerManager. To ustawienie powoduje, że odtwarzacz wznowuje odtwarzanie treści po wczytaniu 1 segmentu.

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

Poniższy przykład pokazuje, jak zastąpić parametr PlaybackConfig w przypadku określonego żądania wczytania za pomocą modułu obsługi informacji o odtwarzaniu multimediów. Moduł obsługi wywołuje metodę getLicenseUrlForMedia zaimplementowaną w aplikacji, aby uzyskać licenseUrl z contentId bieżącego elementu.

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

Detektor zdarzeń

Pakiet Web Receivedr SDK umożliwia aplikacji Web Odbiornika obsługę zdarzeń odtwarzacza. Detektor zdarzeń przyjmuje parametr cast.framework.events.EventType (lub tablicę tych parametrów) określający zdarzenia, które powinny go uruchamiać. Wstępnie skonfigurowane tablice funkcji cast.framework.events.EventType, które są przydatne do debugowania, znajdziesz tutaj: cast.framework.events.category. Parametr zdarzenia dostarcza dodatkowe informacje o zdarzeniu.

Jeśli na przykład chcesz wiedzieć, kiedy następuje zmiana mediaStatus, możesz obsługiwać to zdarzenie za pomocą tej logiki:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

Przechwytywanie wiadomości

Pakiet Web Receivedr SDK umożliwia aplikacji internetowej odbiornika przechwytywanie wiadomości i wykonywanie na nich niestandardowego kodu. Moduł do przechwytywania wiadomości korzysta z parametru cast.framework.messages.MessageType określającego, jaki typ wiadomości ma być przechwytywany.

Obiekt przechwytujący powinien zwracać zmodyfikowane żądanie lub obietnicę, która kończy się ze zmodyfikowaną wartością żądania. Zwrócenie null uniemożliwi wywołanie domyślnego modułu obsługi wiadomości. Więcej informacji znajdziesz w sekcji Wczytywanie multimediów.

Jeśli np. chcesz zmienić dane żądania wczytania, możesz je przechwycić i zmodyfikować w ten sposób:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

Obsługa błędów

Jeśli w przechwycie wiadomości występują błędy, Twoja aplikacja Web Odbieranie powinna zwracać właściwe wartości cast.framework.messages.ErrorType i cast.framework.messages.ErrorReason.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

Przechwytywanie wiadomości a detektor zdarzeń

Oto niektóre kluczowe różnice między przechwytywaniem wiadomości a detektorem zdarzeń:

  • Detektor zdarzeń nie umożliwia modyfikowania danych żądania.
  • Detektor zdarzeń najlepiej nadaje się do uruchamiania statystyk lub funkcji niestandardowej.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • Przechwytywanie wiadomości umożliwia odsłuchanie, przechwycenie wiadomości i zmianę samych danych żądania.
  • Przechwytywanie wiadomości najlepiej sprawdza się w przypadku obsługi niestandardowej logiki związanej z danymi żądania.

Wczytuję multimedia

MediaInformation ma wiele właściwości, które umożliwiają wczytywanie multimediów w wiadomości cast.framework.messages.MessageType.LOAD, w tym entity, contentUrl i contentId.

  • entity to sugerowana właściwość, której warto używać w implementacji zarówno w przypadku aplikacji nadawcy, jak i odbiorcy. Właściwość to URL precyzyjnego linku, który może być playlistą lub treściami multimedialnymi. Należy przeanalizować ten adres URL i wypełnić co najmniej jedno z 2 pozostałych pól.
  • Wartość contentUrl odpowiada odtwarzalnemu adresowi URL, którego odtwarzacz użyje do wczytania treści. Na przykład ten adres URL może wskazywać plik manifestu DASH.
  • Elementem contentId może być adres URL odtwarzanych treści (podobny do właściwości contentUrl) lub unikalny identyfikator wczytywanych treści lub playlisty. Jeśli używasz tej właściwości jako identyfikatora, aplikacja powinna wypełniać w elemencie contentUrl adres URL z możliwością odtworzenia.

Sugerujemy użycie parametru entity do zapisania rzeczywistego identyfikatora lub kluczowych parametrów, a contentUrl jako adresu URL multimediów. Przykład tego znajdziesz w tym fragmencie, gdzie entity występuje w żądaniu LOAD i pobierany jest możliwy do odtworzenia contentUrl:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

Możliwości urządzenia

Metoda getDeviceCapabilities udostępnia informacje o urządzeniu przesyłającym i podłączonym do niego urządzeniu wideo lub audio. Metoda getDeviceCapabilities zapewnia informacje o pomocy Asystenta Google, Bluetootha oraz połączonych urządzeń z wyświetlaczem i urządzeniami audio.

Ta metoda zwraca obiekt, do którego możesz wysłać zapytanie, przekazując jedną z określonych wartości wyliczeniowych, aby uzyskać informacje o możliwościach urządzenia dla tej wyliczenia. Wyliczenia są zdefiniowane w polu cast.framework.system.DeviceCapabilities.

W tym przykładzie sprawdzisz, czy odbiornik internetowy może odtwarzać treści HDR i DolbyVision (DV) odpowiednio za pomocą klawiszy IS_HDR_SUPPORTED i IS_DV_SUPPORTED.

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

Obsługa interakcji użytkownika

Użytkownik może wchodzić w interakcje z Twoją aplikacją internetową za pomocą aplikacji nadawcy (w przeglądarce, na Androidzie lub iOS), poleceń głosowych na urządzeniach z Asystentem, sterowania dotykowego na inteligentnych ekranach i pilota zdalnego na urządzeniach z Androidem TV. Pakiet SDK Cast udostępnia różne interfejsy API, które pozwalają aplikacji internetowej odbiornika na obsługę tych interakcji, aktualizowanie interfejsu aplikacji za pomocą stanów działań użytkownika oraz opcjonalnie wysyłanie zmian w celu zaktualizowania usług backendu.

Obsługiwane polecenia dotyczące multimediów

Stany elementów sterujących interfejsu są wywoływane przez MediaStatus.supportedMediaCommands w przypadku rozszerzonych kontrolerów, odbiorników i zdarzeń pilota działających na urządzeniach dotykowych oraz aplikacji odbierających na urządzeniach z Androidem TV. Gdy w usłudze włączony jest określony zapis bitowy Command, powiązane z nim przyciski będą włączone. Jeśli wartość nie jest ustawiona, przycisk jest wyłączony. Te wartości można zmienić w odbiorniku internetowym przez:

  1. Za pomocą PlayerManager.setSupportedMediaCommands ustaw konkretny parametr Commands
  2. Dodawanie nowego polecenia w addSupportedMediaCommands
  3. Usuwanie istniejącego polecenia za pomocą removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Gdy odbiorca przygotuje zaktualizowany MediaStatus, będzie on zawierał zmiany we właściwości supportedMediaCommands. Gdy zostanie on opublikowany, połączone aplikacje nadawców odpowiednio zaktualizują przyciski w interfejsie.

Więcej informacji o obsługiwanych poleceniach multimedialnych i urządzeniach dotykowych znajdziesz w przewodniku Accessing UI controls.

Zarządzanie stanami działań użytkownika

Gdy użytkownicy korzystają z interfejsu lub wysyłają polecenia głosowe, mogą sterować odtwarzaniem treści i właściwości związanych z odtwarzanym elementem. Żądania sterujące odtwarzaniem są obsługiwane automatycznie przez pakiet SDK. Żądania modyfikujące właściwości odtwarzanego elementu, takie jak polecenie LIKE, wymagają, by je obsługiwała aplikacja odbierająca. Pakiet SDK udostępnia serię interfejsów API do obsługi tego typu żądań. Aby spełnić te warunki, należy wykonać te czynności:

  • Podczas wczytywania elementu multimedialnego skonfiguruj MediaInformation userActionStates z preferencjami użytkownika.
  • Przechwyć USER_ACTION wiadomości i ustal żądane działanie.
  • Zaktualizuj MediaInformation UserActionState, aby zaktualizować interfejs.

Ten fragment kodu przechwytuje żądanie LOAD i wypełnia MediaInformation obiektu LoadRequestData. W takim przypadku użytkownikowi podoba się wczytywane treści.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

Poniższy fragment kodu przechwytuje komunikat USER_ACTION i obsługuje wywołanie backendu z żądaną zmianą. Następnie wywołuje, aby zaktualizować UserActionState w odbiorniku.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

Ten fragment kodu symuluje wywołanie usługi backendu. Funkcja sprawdza UserActionRequestData pod kątem typu zmiany żądanej przez użytkownika i wykonuje wywołanie sieciowe tylko wtedy, gdy działanie jest obsługiwane przez backend.

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

Ten fragment kodu pobiera UserActionRequestData i dodaje lub usuwa UserActionState z MediaInformation. Zaktualizowanie UserActionState elementu MediaInformation zmienia stan przycisku powiązanego z żądanym działaniem. Ta zmiana jest widoczna w interfejsie sterowania inteligentnym ekranem, w aplikacji do pilota i w interfejsie Androida TV. Jest też rozpowszechniana w wychodzących wiadomościach MediaStatus w celu aktualizowania interfejsu rozszerzonego kontrolera w przypadku nadawców iOS i Androida.

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

Polecenia głosowe

Poniższe polecenia multimedialne są obecnie obsługiwane w pakiecie SDK odbiornika internetowego dla urządzeń z Asystentem. Domyślne implementacje tych poleceń można znaleźć w pliku cast.framework.PlayerManager.

Polecenie Opis
Google Play Odtwarzanie i wznawianie odtwarzania od momentu wstrzymania.
Wstrzymaj Wstrzymaj odtwarzanie obecnie odtwarzanych treści.
Wstecz Przejdź do poprzedniego elementu w kolejce multimediów.
Dalej Przejdź do następnego elementu w kolejce multimediów.
Zatrzymaj Zatrzymaj aktualnie odtwarzane multimedia.
Nie powtarzaj Wyłącz powtarzanie elementów multimedialnych w kolejce po zakończeniu odtwarzania ostatniego elementu w kolejce.
Powtórz singiel Powtarzaj aktualnie odtwarzane treści bez ograniczeń czasowych.
Powtarzaj wszystko Powtórz wszystkie elementy z kolejki po odtworzeniu ostatniego elementu.
Powtarzaj wszystko i Odtwarzaj losowo Po zakończeniu odtwarzania ostatniego elementu w kolejce włącz odtwarzanie losowe i powtórz wszystkie elementy w kolejce.
Odtwarzaj losowo Losowe odtwarzanie multimediów z kolejki multimediów.
Napisy WŁĄCZONE / WYŁĄCZONE Włącz / wyłącz napisy w multimediach. Opcje włączania i wyłączania znajdziesz też w zależności od języka.
Przewiń do czasu bezwzględnego Przechodzi do określonego czasu bezwzględnego.
Przewijanie do czasu względem bieżącego czasu Powoduje przejście do przodu lub do tyłu o wybrany okres względem bieżącego czasu odtwarzania.
Zagraj jeszcze raz Uruchom ponownie aktualnie odtwarzane multimedia lub odtwórz ostatnio odtwarzany element multimedialny, jeśli nic nie jest odtwarzane.
Ustawianie szybkości odtwarzania Zróżnicuj szybkość odtwarzania multimediów. To powinno być obsługiwane domyślnie. Do zastępowania przychodzących żądań stawek możesz używać narzędzia do przechwytywania wiadomości SET_PLAYBACK_RATE.

Obsługiwane polecenia multimedialne w przypadku poleceń głosowych

Aby polecenia głosowe nie uruchamiały ich na urządzeniu z Asystentem, musisz najpierw ustawić obsługiwane polecenia multimedialne, które planujesz obsługiwać. Następnie musisz wymusić te polecenia, włączając właściwość CastReceiverOptions.enforceSupportedCommands. Interfejs użytkownika na urządzeniach nadawców obsługujących pakiet SDK Cast oraz na urządzeniach obsługujących dotyk zmieni się, aby odzwierciedlić te konfiguracje. Jeśli flaga nie jest włączona, przychodzące polecenia głosowe są wykonywane.

Jeśli na przykład zezwalasz na PAUSE w aplikacjach nadawców i urządzeniach z włączonym ekranem dotykowym, musisz też skonfigurować odbiornik, aby uwzględniał te ustawienia. Po skonfigurowaniu wszystkie przychodzące polecenia głosowe będą usuwane, jeśli nie znajdują się na liście obsługiwanych poleceń.

W poniższym przykładzie przy uruchamianiu CastReceiverContext podajemy zmienną CastReceiverOptions. Dodaliśmy obsługę polecenia PAUSE i wymuszono odtwarzanie tylko tego polecenia w odtwarzaczu. Jeśli polecenie głosowe zażąda innej operacji, np. SEEK, zostanie ona odrzucona. Użytkownik otrzyma powiadomienie, że polecenie nie jest jeszcze obsługiwane.

const context = cast.framework.CastReceiverContext.getInstance();

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

Możesz zastosować oddzielną logikę do każdego polecenia, które chcesz ograniczyć. Usuń flagę enforceSupportedCommands, a w przypadku każdego polecenia, które chcesz zablokować, możesz przechwycić wiadomość przychodzącą. Przechwytujemy tu żądanie dostarczone przez pakiet SDK, dzięki czemu polecenia SEEK wysyłane do urządzeń z Asystentem nie uruchamiają wyszukiwania w aplikacji internetowej odbiornika.

W przypadku poleceń multimedialnych, których aplikacja nie obsługuje, zwracaj odpowiednią przyczynę błędu, na przykład NOT_SUPPORTED.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

Tworzenie w tle na podstawie aktywności związanej z głosem

Jeśli platforma przesyłająca odtwarza dźwięk Twojej aplikacji w tle z powodu działań Asystenta, takich jak słuchanie mowy użytkownika lub mówienie, odpowiedź FocusState jest wysyłana do aplikacji odbiornika internetowego (NOT_IN_FOCUS). Po zakończeniu aktywności zostanie wysłana kolejna wiadomość w firmie IN_FOCUS. W zależności od aplikacji i odtwarzanych multimediów możesz wstrzymać odtwarzanie multimediów, gdy FocusState ma wartość NOT_IN_FOCUS, przechwytując wiadomość typu FOCUS_STATE.

Warto na przykład wstrzymać odtwarzanie audiobooka, gdy Asystent odpowie na pytanie użytkownika.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

Język napisów określony przez głos

Jeśli użytkownik nie poda języka napisów, będzie używany ten sam język, w którym zostało wypowiedzone polecenie. W takich sytuacjach parametr isSuggestedLanguage wiadomości przychodzącej wskazuje, czy powiązany język został zaproponowany lub jawnie zażądany przez użytkownika.

Na przykład isSuggestedLanguage ma wartość true dla polecenia „OK Google, włącz napisy”, ponieważ język został ustalony na podstawie języka, w którym wymówiono polecenie. Jeśli język jest wyraźnie wymagany, na przykład w sekcji „OK Google, włącz napisy angielskie”, isSuggestedLanguage ma wartość false.

Metadane i przesyłanie głosowe

Chociaż polecenia głosowe są domyślnie obsługiwane przez odbiornik internetowy, musisz zadbać o pełne i dokładne metadane treści. Dzięki temu będziesz mieć pewność, że polecenia głosowe będą obsługiwane przez Asystenta, a metadane będą się prawidłowo wyświetlać w nowych typach interfejsów, takich jak aplikacja Google Home czy inteligentne ekrany, np. w Google Home Hub.

Przenoszenie strumienia

Zachowanie stanu sesji jest podstawą przesyłania strumienia, w ramach którego użytkownicy mogą przenosić strumienie audio i wideo między urządzeniami za pomocą poleceń głosowych, aplikacji Google Home lub inteligentnych ekranów. Odtwarzanie multimediów zatrzymuje się na jednym urządzeniu (źródło), a następnie jest kontynuowane na innym (miejscu docelowym). Każde urządzenie przesyłające z najnowszym oprogramowaniem może służyć jako źródło lub miejsca docelowe w przesyłaniu strumieniowym.

Proces przenoszenia transmisji między zdarzeniami:

  1. Na urządzeniu źródłowym:
    1. Odtwarzanie multimediów zatrzymuje się.
    2. Aplikacja Web Receivedr odbiera polecenie zapisania aktualnego stanu multimediów.
    3. Aplikacja Web Receivedr jest wyłączona.
  2. Na urządzeniu docelowym:
    1. Aplikacja Web Receivedr została załadowana.
    2. Aplikacja Web Receivedr odbiera polecenie przywrócenia zapisanego stanu multimediów.
    3. Odtwarzanie multimediów zostanie wznowione.

Elementy stanu mediów obejmują:

  • Określona pozycja lub sygnatura czasowa utworu, filmu lub elementu multimedialnego.
  • Jest w szerszej kolejce (np. na playliście lub w radiu wykonawcy).
  • Uwierzytelniony użytkownik.
  • Stan odtwarzania (np. odtwarzanie lub wstrzymanie).

Włączam przenoszenie strumienia

Aby zaimplementować przesyłanie strumienia w odbiorniku internetowym:

  1. Zaktualizuj supportedMediaCommands za pomocą polecenia STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. Opcjonalnie zastąp moduły do przechwytywania wiadomości SESSION_STATE i RESUME_SESSION zgodnie z opisem w sekcji Zachowywanie stanu sesji. Zastąp je tylko wtedy, gdy dane niestandardowe muszą być przechowywane w ramach zrzutu sesji. W przeciwnym razie domyślna implementacja zachowywania stanów sesji będzie obsługiwać przenoszenie strumienia.

Zachowuję stan sesji

Pakiet Web Receivedr SDK zapewnia domyślną implementację aplikacji do odbierania treści internetowych w celu zachowania stanów sesji przez zrobienie zrzutu bieżącego stanu multimediów, przekształcenie go w żądanie wczytania i wznowienie sesji z żądaniem wczytania.

W razie potrzeby żądanie wczytania wygenerowane przez odbiornik internetowy można zastąpić w module przechwytywania wiadomości SESSION_STATE. Jeśli chcesz dodać do żądania wczytania dane niestandardowe, umieść je w zadaniu loadRequestData.customData.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

Dane niestandardowe można pobrać z loadRequestData.customData w module przechwytywania wiadomości RESUME_SESSION.

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

Wstępne wczytywanie treści

Odbiornik internetowy obsługuje wstępne wczytywanie elementów multimedialnych po bieżącym elemencie odtwarzania w kolejce.

Operacja wstępnego wczytywania pobiera wstępnie kilka segmentów nadchodzących elementów. Specyfikacja jest określana na podstawie wartości preloadTime w obiekcie QueueItem (jeśli nie jest podana, domyślnie jest to 20 sekund). Czas jest wyrażony w sekundach, względem końca odtwarzanego elementu . Dozwolone są tylko wartości dodatnie. Jeśli np. wartość to 10 sekund, ten element zostanie wstępnie wczytany 10 sekund przed zakończeniem czasu poprzedniego. Jeśli czas wstępnego wczytywania jest dłuższy niż pozostały czas elementu currentItem, wstępne wczytywanie nastąpi jak najszybciej. Jeśli więc w elemencie kolejki jest określona bardzo duża wartość wstępnego wczytywania, można uzyskać efekt, ponieważ za każdym razem, gdy odtwarzamy bieżący element, wstępnie wczytujemy kolejny element. Ustawienie i wybór tego ustawienia pozostawiamy jednak deweloperowi, ponieważ ta wartość może mieć wpływ na przepustowość i wydajność strumieniowania aktualnie odtwarzanego elementu.

Wstępne wczytywanie będzie domyślnie działać w przypadku treści HLS, DASH i płynnego przesyłania strumieniowego.

Zwykłe pliki wideo i audio MP4, np. MP3, nie będą wstępnie wczytywane, ponieważ urządzenia przesyłające obsługują tylko jeden element multimedialny i nie można ich używać do wstępnego wczytywania istniejącego elementu treści, gdy wciąż jest odtwarzany.

Komunikaty niestandardowe

Wymiana wiadomości to kluczowa metoda interakcji z aplikacjami odbierającymi dane z sieci.

Nadawca wysyła wiadomości do odbiornika internetowego przy użyciu interfejsów API nadawcy na platformie uruchomionej przez nadawcę (Android, iOS lub internet). Obiekt zdarzenia (który jest prezentacją komunikatu) przekazywany do odbiorników zawiera element danych (event.data), gdzie dane pobierają właściwości określonego typu zdarzenia.

Aplikacja Web Receivedr może nasłuchiwać wiadomości w określonej przestrzeni nazw. Dzięki temu aplikacja Odbiorca internetu obsługuje ten protokół przestrzeni nazw. Od tej pory wszyscy nadawcy, którzy chcą komunikować się w tej przestrzeni nazw, korzystają z odpowiedniego protokołu.

Wszystkie przestrzenie nazw są zdefiniowane przez ciąg znaków i muszą zaczynać się od „urn:x-cast:”, po którym następuje dowolny ciąg. np. „urn:x-cast:com.example.cast.mynamespace”.

Oto fragment kodu, który umożliwia odbiornikowi internetowemu odsłuchiwanie niestandardowych wiadomości od połączonych nadawców:

const context = cast.framework.CastReceiverContext.getInstance();

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

Podobnie aplikacje Web Recipient mogą wysyłać wiadomości do połączonych nadawców, aby informować nadawców o stanie odbiornika internetowego. Aplikacja odbierająca pocztę może wysyłać wiadomości przy użyciu sendCustomMessage(namespace, senderId, message) w CastReceiverContext. Odbiornik internetowy może wysyłać wiadomości do poszczególnych nadawców w odpowiedzi na otrzymaną wiadomość lub z powodu zmiany stanu aplikacji. Poza komunikacją typu punkt do punktu (z limitem 64 KB) odbiornik internetowy może również przesyłać wiadomości do wszystkich połączonych nadawców.

Przesyłanie na urządzenia audio

Informacje na temat odtwarzania samego dźwięku znajdziesz w przewodniku po Google Cast na urządzenia audio.

Android TV

W tej sekcji omawiamy, w jaki sposób odbiornik internetowy Google wykorzystuje Twoje dane wejściowe do odtwarzania, a także opisujemy zgodność z Androidem TV.

Integracja aplikacji z pilotem

Odbiornik internetowy Google działający na urządzeniu z Androidem TV zamienia sygnały wejściowe elementów sterujących urządzenia (np. pilota ręcznego) jako wiadomości o odtwarzaniu multimediów zdefiniowane w przestrzeni nazw urn:x-cast:com.google.cast.media, zgodnie z opisem w sekcji Komunikaty o odtwarzaniu multimediów. Twoja aplikacja musi obsługiwać te komunikaty, aby sterować odtwarzaniem multimediów w aplikacji i umożliwić podstawowe sterowanie odtwarzaniem z poziomu sygnałów wejściowych Androida TV.

Wytyczne dotyczące zgodności z Androidem TV

Oto kilka rekomendacji i typowych pułapek, których należy unikać, gdy chcesz się upewnić, że Twoja aplikacja jest zgodna z Androidem TV:

  • Pamiętaj, że ciąg znaków klienta użytkownika zawiera zarówno ciąg „Android”, jak i „CrKey”. Niektóre witryny mogą przekierowywać do witryny tylko na urządzenia mobilne, ponieważ wykrywają etykietę „Android”. Nie zakładaj, że ciąg „Android” w ciągu klienta użytkownika zawsze oznacza użytkownika mobilnego.
  • Do pobierania danych stos multimediów Androida może używać przezroczystego GZIP. Upewnij się, że dane multimediów są w stanie odpowiadać na żądania Accept-Encoding: gzip.
  • Zdarzenia multimedialne HTML5 na Androidzie TV mogą być wywoływane w innych momentach niż w przypadku Chromecasta. Może to ujawnić problemy, które były na nim ukryte.
  • Do aktualizowania multimediów używaj zdarzeń związanych z multimediami wywoływanych przez elementy <audio>/<video>, takie jak timeupdate, pause i waiting. Unikaj zdarzeń związanych z siecią, takich jak progress, suspend i stalled, ponieważ zależą one zwykle od platformy. Więcej informacji o obsłudze zdarzeń multimediów w odbiorniku znajdziesz w sekcji Zdarzenia multimediów.
  • Podczas konfigurowania certyfikatów HTTPS witryny odbiorcy pamiętaj o dodaniu certyfikatów pośrednich CA. Na stronie testowej Qualsys SSL możesz sprawdzić, czy zaufana ścieżka certyfikacji Twojej witryny zawiera certyfikat CA oznaczony etykietą „dodatkowe pobranie”, która może nie wczytywać się na platformach opartych na Androidzie.
  • Chromecast wyświetla stronę odbiornika na płycie graficznej 720p, ale inne platformy przesyłające, w tym Android TV, mogą ją wyświetlać w rozdzielczości 1080p. Zadbaj o to, aby strona odbiorcy skalowała się płynnie w różnych rozdzielczościach.