Dodaj podstawowe funkcje do niestandardowego odbiornika internetowego

Ta strona zawiera fragmenty kodu i opisy funkcji dostępnych na potrzeby niestandardowej aplikacji odbiornika internetowego.

  1. Element cast-media-player reprezentujący wbudowany interfejs odtwarzacza udostępniany przez odbiornik internetowy.
  2. Niestandardowe style elementu cast-media-player przypominające styl CSS, takie jak background-image, splash-image i font-family.
  3. Element skryptu do wczytywania platformy Web Receiver.
  4. z kodem 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 Receiver.
  9. Wywołanie JavaScriptu do uruchomienia aplikacji Web Receiver.

Konfiguracja i opcje aplikacji

Konfigurowanie aplikacji

CastReceiverContext to najbardziej zewnętrzna klasa widoczna dla programisty. Zajmuje się ładowaniem bazowych bibliotek i inicjowaniem pakietu SDK odbiornika internetowego. Pakiet SDK udostępnia interfejsy API, które umożliwiają deweloperom aplikacji konfigurowanie pakietu SDK za pomocą CastReceiverOptions. Te konfiguracje są oceniane raz na uruchomienie aplikacji i przekazywane do pakietu SDK podczas ustawiania opcjonalnego parametru w wywołaniu start.

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

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

Konfigurowanie odtwarzacza

Podczas wczytywania treści pakiet Web Receiver SDK umożliwia skonfigurowanie zmiennych odtwarzania, takich jak informacje o DRM, a także ponawianie konfiguracji i moduły obsługi żądań za pomocą cast.framework.PlaybackConfig. Te informacje są przetwarzane przez PlayerManager i sprawdzane w momencie tworzenia odtwarzaczy. Odtwarzacze są tworzone za każdym razem, gdy do pakietu SDK odbiornika internetowego trafia nowe dane. Modyfikacje elementu PlaybackConfig po utworzeniu odtwarzacza są sprawdzane przy następnym wczytywaniu treści. Pakiet SDK udostępnia te metody modyfikowania zasobu 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 jest stosowane we wszystkich kolejnych wczytywaniu lub dopóki nie zostanie ponownie zastąpione.
  • PlayerManager.setMediaPlaybackInfoHandler(), aby zastosować dodatkowe konfiguracje tylko do elementu multimedialnego wczytywanego na podstawie bieżących konfiguracji. Moduł obsługi jest wywoływany tuż przed utworzeniem odtwarzacza. Wprowadzone tutaj zmiany nie są trwałe i nie są uwzględniane w zapytaniach wysyłanych do getPlaybackConfig(). Po wczytaniu następnego elementu multimedialnego ten moduł obsługi jest wywoływany ponownie.

Poniższy przykład pokazuje, jak ustawić PlaybackConfig podczas inicjowania CastReceiverContext. Konfiguracja zastępuje żądania wychodzące dotyczące uzyskiwania plików manifestu. Moduł obsługi określa, że żądania kontroli dostępu CORS powinny być wysyłane przy użyciu 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ć zmienną PlaybackConfig za pomocą metod pobierania i ustawiania dostępnych w zasadzie PlayerManager. To ustawienie powoduje, że odtwarzacz wznawia odtwarzanie treści po załadowaniu jednego 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ć PlaybackConfig w konkretnym żądaniu wczytywania za pomocą modułu obsługi informacji o odtwarzaniu multimediów. Moduł obsługi wywołuje zaimplementowane przez aplikację metodę getLicenseUrlForMedia, aby uzyskać licenseUrl z obiektu contentId bieżącego elementu.

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

  return playbackConfig;
});

Detektor zdarzeń

Pakiet Web Receiver SDK umożliwia aplikacji odbiornik internetowy obsługę zdarzeń odtwarzacza. Detektor zdarzeń pobiera parametr cast.framework.events.EventType (lub tablicę tych parametrów), który określa zdarzenia, które mają aktywować detektor. Wstępnie skonfigurowane tablice cast.framework.events.EventType, które przydają się przy debugowaniu, znajdziesz w cast.framework.events.category. Parametr zdarzenia zawiera dodatkowe informacje o zdarzeniu.

Jeśli na przykład chcesz wiedzieć, kiedy jest transmitowana zmiana mediaStatus, możesz obsłużyć zdarzenie, korzystając z 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 Receiver SDK umożliwia aplikacji odbiornik internetowy przechwytywanie wiadomości i wykonywanie w nich niestandardowego kodu. Funkcja przechwytująca wiadomości przyjmuje parametr cast.framework.messages.MessageType, który określa typ wiadomości do przechwycenia.

Element przechwytujący powinien zwrócić zmodyfikowane żądanie lub obietnicę, która zakoń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 artykule Wczytywanie multimediów.

Jeśli np. chcesz zmienić dane żądania wczytywania, możesz skorzystać z tej logiki, aby je przechwycić i zmodyfikować:

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

Gdy w punkcie przechwytującym wiadomości wystąpią błędy, aplikacja Web Receiver powinna zwrócić odpowiednie 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 kilka kluczowych różnic między przechwytywaniem wiadomości a detektorem zdarzeń:

  • Detektor zdarzeń nie pozwala na modyfikowanie danych żądania.
  • Detektor zdarzeń najlepiej nadaje się do aktywowania analiz lub funkcji niestandardowych.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • Przechwytywanie wiadomości pozwala odsłuchać wiadomość i przechwycić ją, a następnie samodzielnie zmodyfikować dane żądania.
  • Przechwytywanie wiadomości sprawdza się najlepiej w przypadku niestandardowej logiki w przypadku danych żądań.

Wczytuję multimedia

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

  • entity to sugerowana właściwość do użycia 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. Aplikacja powinna przeanalizować ten adres URL i wypełnić co najmniej jedno z pozostałych 2 pól.
  • contentUrl odpowiada odtwarzanemu adresowi URL, którego odtwarzacz użyje do wczytania treści. Na przykład ten adres URL może wskazywać plik manifestu DASH.
  • Obiekt contentId może być adresem URL treści możliwych do odtworzenia (podobnym do właściwości contentUrl) albo unikalnym identyfikatorem wczytywanej treści lub playlisty. Jeśli używasz tej właściwości jako identyfikatora, aplikacja powinna uzupełniać w polu contentUrl adres URL gry.

Zalecamy używanie właściwości entity do przechowywania rzeczywistego identyfikatora lub kluczowych parametrów i używanie contentUrl jako adresu URL multimediów. Oto przykładowy fragment kodu, który zawiera element entity w żądaniu LOAD i pobrany dostępny 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;
        });
    });

Funkcje urządzenia

Metoda getDeviceCapabilities przekazuje informacje z urządzenia podłączonego do urządzenia przesyłającego oraz podłączonego do niego urządzenia wideo lub audio. Metoda getDeviceCapabilities udostępnia informacje pomocy dotyczące Asystenta Google, Bluetootha oraz połączonych urządzeń wyświetlających i audio.

Ta metoda zwraca obiekt, o który można wykonać zapytanie, przekazując jedną ze podanych wartości wyliczeniowych w celu uzyskania możliwości urządzenia w przypadku tej wartości wyliczeniowej. Wyliczenia są zdefiniowane w zadaniu cast.framework.system.DeviceCapabilities.

Ten przykład pozwala sprawdzić, czy odbiornik internetowy może odtwarzać treści HDR i DolbyVision (DV) odpowiednio przy użyciu 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 korzystać z aplikacji odbiornika internetowego, używając aplikacji nadawcy (w przeglądarce, na Androidzie lub iOS), poleceń głosowych na urządzeniach z Asystentem, sterowania dotykowego na inteligentnych ekranach i pilotów na urządzeniach z Androidem TV. SDK Cast udostępnia różne interfejsy API, które pozwalają aplikacji Web Receiver na obsługę tych interakcji, aktualizowanie interfejsu aplikacji za pomocą stanów działań użytkownika i opcjonalnie wysyłanie zmian w celu zaktualizowania usług backendu.

Obsługiwane polecenia multimedialne

Stany elementów sterujących interfejsu są określane przez parametr MediaStatus.supportedMediaCommands w przypadku rozszerzonych kontrolerów dla nadawców na iOS i Androida, aplikacji odbiornika i zdalnego sterowania działającego na urządzeniach dotykowych oraz aplikacji odbiorników na urządzeniach z Androidem TV. Gdy we właściwości włączony jest określony tag bitowy Command, przyciski związane z tym działaniem są włączone. Jeśli wartość nie jest ustawiona, przycisk jest wyłączony. Te wartości można zmienić w odbiorniku internetowym przez:

  1. Użycie właściwości PlayerManager.setSupportedMediaCommands do skonfigurowania konkretnego elementu Commands
  2. Dodaję nowe polecenie za pomocą addSupportedMediaCommands
  3. Usunięcie dotychczasowego polecenia przy użyciu polecenia removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Gdy odbiorca przygotuje zaktualizowany MediaStatus, uwzględni zmiany we właściwości supportedMediaCommands. Gdy stan jest transmitowany, połączone aplikacje nadawców odpowiednio zaktualizują przyciski w swoim 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żytkowników

Gdy użytkownicy korzystają z interfejsu lub wysyłają polecenia głosowe, mogą kontrolować odtwarzanie treści i właściwości związane z odtwarzanym elementem. Pakiet SDK obsługuje żądania sterujące odtwarzaniem automatycznie. Żądania, które modyfikują właściwości odtwarzanego aktualnie elementu (np. polecenie LIKE), wymagają, aby aplikacja odbierająca je obsługowała. Pakiet SDK udostępnia szereg interfejsów API do obsługi tego typu żądań. W tym celu należy:

  • Ustaw MediaInformation userActionStates z preferencjami użytkownika podczas wczytywania elementu multimedialnego.
  • Przechwyć USER_ACTION wiadomości i określ wymagane działanie.
  • Aby zaktualizować interfejs użytkownika, zaktualizuj MediaInformation UserActionState.

Ten fragment kodu przechwytuje żądanie LOAD i wypełnia żądanie LoadRequestDataelementu MediaInformation. W tym przypadku użytkownikowi podoba się wczytywana treść.

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

Ten fragment kodu przechwytuje komunikat USER_ACTION i obsługuje wywoływanie backendu z żądaną zmianą. Następnie wysyła wywołanie, by zaktualizować UserActionState na 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 w elemencie UserActionRequestData typ zmiany, o którą prosił użytkownik, i wywołuje wywołanie sieci 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 wykorzystuje 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 do sterowania inteligentnym ekranie, aplikacji Pilot i interfejsie Androida TV. Jest też transmitowany przez wiadomości wychodzące MediaStatus w celu zaktualizowania interfejsu rozwiniętego kontrolera dla nadawców na urządzeniach z iOS i Androidem.

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 Web Receiver na urządzenia z Asystentem. Domyślne implementacje tych poleceń znajdziesz tutaj: cast.framework.PlayerManager.

Polecenie Opis
Google Play Odtwarzanie lub wznowienie odtwarzania od momentu wstrzymania.
Wstrzymaj Wstrzymaj odtwarzane treści.
Wstecz Przejdź do poprzedniego elementu multimedialnego w kolejce.
Dalej Przejdź do następnego elementu w kolejce multimediów.
Zatrzymaj Zatrzymaj odtwarzane multimedia.
Nie powtarzaj niczego Wyłącz powtarzanie elementów multimedialnych w kolejce po zakończeniu odtwarzania ostatniego elementu w kolejce.
Powtórz jeden raz Powtarzaj cały czas odtwarzane multimedia.
Powtórz wszystko Powtórz wszystkie elementy w kolejce po odtworzeniu ostatniego elementu w kolejce.
Powtórz wszystko i odtwórz losowo Po zakończeniu odtwarzania ostatniego elementu w kolejce należy je losowo odtwarzać, a następnie powtórzyć wszystkie elementy w kolejce.
Odtwarzaj losowo Losowe odtwarzanie elementów multimedialnych w kolejce multimediów.
Napisy WŁĄCZONE / WYŁĄCZONE Włącz / wyłącz napisy w multimediach. Opcje włączania i wyłączania są również dostępne w poszczególnych językach.
Przewijanie do bezwzględnego czasu Przechodzi do określonego czasu bezwzględnego.
Przewiń do czasu w odniesieniu do czasu bieżącego Przewija do przodu lub do tyłu o określony przedział czasu w stosunku do bieżącego czasu odtwarzania.
Zagraj jeszcze raz Uruchom ponownie aktualnie odtwarzane multimedia lub odtwórz ostatnio odtwarzany element, jeśli nic obecnie nie jest odtwarzane.
Ustawianie szybkości odtwarzania Zróżnicowanie szybkości odtwarzania multimediów. To ustawienie powinno być obsługiwane domyślnie. Do zastępowania przychodzących próśb o stawkę możesz użyć przechwytującego wiadomości SET_PLAYBACK_RATE.

Obsługiwane polecenia multimedialne z użyciem głosu

Aby polecenie głosowe nie uruchamiało polecenia multimedialnego na urządzeniu z Asystentem, musisz najpierw ustawić obsługiwane polecenia multimedialne, które chcesz obsługiwać. Potem musisz wymusić te polecenia, włączając właściwość CastReceiverOptions.enforceSupportedCommands. Interfejs nadawców i urządzeń obsługujących dotyk Cast SDK zmieni się, aby odzwierciedlał te konfiguracje. Jeśli flaga nie jest włączona, przychodzące polecenia głosowe będą wykonywane.

Jeśli na przykład zezwalasz na PAUSE w aplikacjach nadawcy i urządzeniach dotykowych, musisz też skonfigurować odbiornik, aby uwzględniał te ustawienia. Po ich 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 podajemy CastReceiverOptions, uruchamiając CastReceiverContext. Dodaliśmy obsługę polecenia PAUSE i zmusiliśmy odtwarzacz do obsługi tylko tego polecenia. Jeśli polecenie głosowe zażąda innej operacji, na przykład SEEK, zostanie ono odrzucone. Użytkownik otrzyma powiadomienie, że to polecenie nie jest jeszcze obsługiwane.

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

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

Do każdego polecenia, które chcesz ograniczyć, możesz zastosować osobną logikę. Usuń flagę enforceSupportedCommands i w przypadku każdego polecenia, dla którego chcesz wprowadzić ograniczenia, możesz przechwycić wiadomość przychodzącą. W tym miejscu przechwytujemy żądanie dostarczone przez pakiet SDK, dzięki czemu polecenia SEEK wysyłane na urządzenia z Asystentem nie uruchamiają wyszukiwania w aplikacji Odbiornik internetowy.

W przypadku poleceń multimedialnych, których Twoja aplikacja nie obsługuje, zwracaj odpowiedni powód 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;
  });

Tło z aktywności związanej z głosem

Jeśli platforma Cast odtwarza w tle dźwięk Twojej aplikacji w wyniku działania Asystenta, np. słuchania wypowiedzi użytkownika lub odpowiadania, po rozpoczęciu działania do aplikacji Web Receiver zostanie wysłany komunikat FocusState o wartości NOT_IN_FOCUS. Po zakończeniu aktywności otrzymasz kolejną wiadomość z adresem IN_FOCUS. W zależności od aplikacji i odtwarzanych multimediów możesz wstrzymać multimedia, gdy FocusState ma wartość NOT_IN_FOCUS, przechwytując wiadomość typu FOCUS_STATE.

Na przykład dobrze jest wstrzymać odtwarzanie audiobooka, gdy Asystent odpowiada na zapytanie 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

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

Na przykład pole isSuggestedLanguage ma wartość true w przypadku polecenia „OK Google, włącz napisy”, ponieważ język został ustalony na podstawie języka polecenia. Jeśli wymagane jest podanie języka, na przykład w „OK Google, włącz angielskie napisy”, isSuggestedLanguage ma wartość false.

Metadane i przesyłanie głosu

Choć polecenia głosowe są domyślnie obsługiwane przez odbiornik internetowy, upewnij się, że metadane Twoich treści są kompletne i dokładne. Dzięki temu będziesz mieć pewność, że Asystent prawidłowo obsługuje polecenia głosowe, a metadane wyświetlają się prawidłowo w nowych typach interfejsów, takich jak aplikacja Google Home i inteligentne ekrany, takie jak Google Home Hub.

Przenoszenie strumienia

Zachowanie stanu sesji jest podstawą przenoszenia strumienia, w ramach której użytkownicy mogą przenosić istniejące strumienie audio i wideo między urządzeniami za pomocą poleceń głosowych, aplikacji Google Home lub inteligentnych ekranów. Multimedia zatrzymują się na jednym urządzeniu (źródle) i na drugim (miejscu docelowym). Każde urządzenie przesyłające z najnowszym oprogramowaniem może służyć jako źródło lub miejsce docelowe podczas przesyłania strumienia.

Przepływ zdarzeń związanych z przeniesieniem strumienia wygląda tak:

  1. Na urządzeniu źródłowym:
    1. Odtwarzanie multimediów zostanie przerwane.
    2. Aplikacja odbiornika internetowego otrzymuje polecenie pozwalające zapisać bieżący stan multimediów.
    3. Aplikacja Web Receiver jest wyłączona.
  2. Na urządzeniu docelowym:
    1. Aplikacja odbiornika internetowego jest wczytana.
    2. Aplikacja odbiornika internetowego otrzymuje polecenie przywrócenia zapisanego stanu multimediów.
    3. Multimedia wznowią odtwarzanie.

Do elementów stanu multimediów należą:

  • Konkretna pozycja lub sygnatura czasowa utworu, filmu lub elementu multimedialnego.
  • umieszczenie go w szerszej kolejce (np. w playlisty lub w radiu wykonawcy).
  • Uwierzytelniony użytkownik.
  • Stan odtwarzania (np. odtwarzanie lub wstrzymanie).

Włączam przenoszenie strumienia

Aby wdrożyć przesyłanie strumienia na odbiorniku internetowym:

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

Zachowywanie stanu sesji

SDK odbiornika internetowego udostępnia domyślną implementację dla aplikacji odbiorników internetowych, aby zachowywał stany sesji przez utworzenie zrzutu bieżącego stanu multimediów, przekształcenie go w żądanie wczytania i wznawianie sesji z żądaniem wczytania.

Żądanie obciążenia wygenerowane przez odbiornik internetowy można w razie potrzeby zastąpić w SESSION_STATE module do przechwytywania. Jeśli do żądania wczytywania chcesz dodać dane niestandardowe, zalecamy umieszczenie ich w narzędziu 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 poziomu loadRequestData.customData w elemencie przechwytującym 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 wczytanie treści

Odbiornik internetowy obsługuje wstępne wczytywanie elementów multimedialnych po aktualnie odtwarzanym elemencie w kolejce.

Operacja wstępnego wczytywania pobiera wstępnie kilka segmentów nadchodzących elementów. Specyfikacja jest wykonywana na wartości preloadTime w obiekcie QueueItem (jeśli nie zostanie podana, domyślna wartość to 20 sekund). Czas jest wyrażony w sekundach w stosunku do końca odtwarzanego elementu . Prawidłowe są tylko wartości dodatnie. Jeśli np. wartość wynosi 10 sekund, element zostanie wstępnie wczytany 10 sekund przed zakończeniem poprzedniego elementu. Jeśli czas wstępnego wczytywania będzie dłuższy niż pozostały czas dla bieżącego elementu, wstępne wczytywanie nastąpi tak szybko, jak to możliwe. Jeśli więc określisz bardzo dużą wartość wstępnego wczytywania w elemencie containerItem, można osiągnąć efekt za każdym razem, gdy odtwarzamy bieżący element, a następny jest już wstępnie wczytywany. To ustawienie pozostawiamy jednak deweloperowi, ponieważ ta wartość może mieć wpływ na przepustowość i wydajność strumieniowania odtwarzanego elementu.

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

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żyć do wstępnego wczytywania, gdy odtwarzany jest istniejący element treści.

Komunikaty niestandardowe

Wymiana wiadomości to kluczowa metoda interakcji w aplikacjach odbiornika internetowego.

Nadawca wysyła wiadomości do odbiornika internetowego, używając interfejsów API nadawcy (Android, iOS, internet). Obiekt zdarzenia (który jest plikiem manifestu wiadomości), który jest przekazywany do detektorów zdarzeń, zawiera element danych (event.data), w którym dane przyjmują właściwości określonego typu zdarzenia.

Aplikacja odbiornika internetowego może zdecydować się na nasłuchiwanie wiadomości z określonej przestrzeni nazw. Dzięki temu aplikacja Web Receiver obsługuje ten protokół przestrzeni nazw. Wtedy to wszyscy połączeni nadawcy, którzy chcą komunikować się w tej przestrzeni nazw, korzystając z odpowiedniego protokołu.

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

Oto fragment kodu, który umożliwia odbiornikowi internetowemu nasł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 odbiornika internetowego mogą informować nadawców o stanie odbiornika internetowego, wysyłając wiadomości do połączonych nadawców. Aplikacja odbiornika internetowego może wysyłać wiadomości za pomocą funkcji sendCustomMessage(namespace, senderId, message) w CastReceiverContext. Odbiorca internetowy może wysyłać wiadomości do konkretnego nadawcy w odpowiedzi na odebraną wiadomość lub z powodu zmiany stanu aplikacji. Poza przesyłaniem danych z punktu do punktu (z limitem 64 KB) odbiornik internetowy może też wysył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, jak odbiornik internetowy Google wykorzystuje Twoje dane wejściowe do odtwarzania, oraz omawia zgodność z Androidem TV.

Integracja aplikacji z pilotem

Odbiornik internetowy Google działający na urządzeniu z Androidem TV tłumaczy dane wejściowe z wejścia sterowania urządzenia (np. ręcznego pilota) jako komunikaty dotyczące odtwarzania multimediów zdefiniowane w przestrzeni nazw urn:x-cast:com.google.cast.media, zgodnie z opisem w sekcji Wiadomości dotyczące odtwarzania multimediów. Aplikacja musi obsługiwać te komunikaty, aby sterować odtwarzaniem multimediów w aplikacji – aby możliwe było podstawowe sterowanie odtwarzaniem z wejścia sterującego Androida TV.

Wytyczne dotyczące zgodności z Androidem TV

Oto kilka zaleceń i typowych problemów, których należy unikać, aby zapewnić zgodność aplikacji 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ć użytkowników do witryn przeznaczonych tylko na urządzenia mobilne, ponieważ wykrywają etykietę „Android”. Nie zakładaj, że „Android” w ciągu znaków klienta użytkownika zawsze wskazuje użytkownika mobilnego.
  • Stos multimediów na Androidzie może używać do pobierania danych przezroczystego GZIP. Upewnij się, że Twoje dane multimedialne mogą reagować na funkcję Accept-Encoding: gzip.
  • Zdarzenia dotyczące multimediów w Androidzie TV mogą być wywoływane w innych momentach niż Chromecast. Może to ujawnić problemy, które były na nim ukryte.
  • Podczas aktualizowania multimediów używaj zdarzeń związanych z multimediami, które są wywoływane przez elementy <audio>/<video>, takie jak timeupdate, pause i waiting. Unikaj używania zdarzeń związanych z siecią, takich jak progress, suspend i stalled, ponieważ zwykle są one zależne od platformy. Więcej informacji o obsłudze zdarzeń multimediów w odbiorniku znajdziesz w artykule Zdarzenia multimedialne.
  • Podczas konfigurowania certyfikatów HTTPS witryny odbiorcy pamiętaj o dołączeniu certyfikatów pośrednich CA. Aby to sprawdzić, zapoznaj się ze stroną testową Qualsys SSL. Jeśli zaufana ścieżka certyfikacji Twojej witryny zawiera certyfikat CA oznaczony etykietą „extra download”, może się ona nie ładować na platformach opartych na Androidzie.
  • Chromecast wyświetla stronę odbiornika na płaszczyźnie graficznej 720p, a inne platformy Cast, takie jak Android TV, mogą wyświetlać stronę w rozdzielczości do 1080p. Zadbaj o to, aby strona odbiorcy płynnie skalowała się w różnych rozdzielczościach.