Dodaj podstawowe funkcje do niestandardowego odbiornika internetowego

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

  1. Element cast-media-player reprezentujący wbudowany interfejs odtwarzacza udostępniany przez odbiornik internetowy.
  2. Niestandardowy styl podobny do CSS dla elementu cast-media-player, który umożliwia określanie stylu różnych elementów interfejsu, takich jak background-image, splash-image i font-family.
  3. Element skryptu do wczytywania platformy Web Receiver.
  4. kod JavaScript do przechwytywania wiadomości i obsługi zdarzeń.
  5. Kolejka do autoodtwarzania.
  6. Opcje konfiguracji odtwarzania.
  7. Opcje ustawiania kontekstu odbiornika internetowego.
  8. Opcje ustawiania poleceń obsługiwanych przez aplikację odbiornika internetowego.
  9. Wywołanie JavaScriptu, które uruchamia aplikację odbiornika internetowego.

Konfiguracja i opcje aplikacji

Konfigurowanie aplikacji

CastReceiverContext to najbardziej zewnętrzna klasa udostępniana programistom. Zarządza ona wczytywaniem bibliotek bazowych 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 podczas uruchamiania aplikacji i przekazywane do pakietu SDK podczas ustawiania opcjonalnego parametru w wywołaniu funkcji start.

W przykładzie poniżej pokazujemy, jak zastąpić domyślne zachowanie w przypadku wykrywania, czy połączenie nadawcy jest nadal aktywne. Gdy odbiornik internetowy nie może komunikować się z nadawcą przez maxInactivity sekund, wysyłane jest zdarzenie SENDER_DISCONNECTED. Konfiguracja poniżej zastępuje ten czas oczekiwania. Może to być przydatne podczas debugowania problemów, ponieważ zapobiega zamknięciu sesji debugowania zdalnego w Chrome przez aplikację odbiornika internetowego, gdy w stanie IDLE nie ma podłą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 konfigurowanie zmiennych odtwarzania, takich jak informacje o DRM, konfiguracje ponawiania i obsługa żądań za pomocą cast.framework.PlaybackConfig. Te informacje są obsługiwane przez PlayerManager i oceniane w momencie tworzenia odtwarzaczy. Odtwarzacze są tworzone za każdym razem, gdy do pakietu SDK odbiornika internetowego przekazywane jest nowe wczytanie. Zmiany w PlaybackConfig po utworzeniu odtwarzacza są oceniane podczas następnego wczytywania 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() – zastąpienie bieżącej konfiguracji. To ustawienie jest stosowane do wszystkich kolejnych wczytań lub do momentu ponownego zastąpienia.
  • PlayerManager.setMediaPlaybackInfoHandler(), aby zastosować dodatkowe konfiguracje tylko do elementu multimedialnego wczytywanego na podstawie bieżących konfiguracji. Procedura obsługi jest wywoływana tuż przed utworzeniem odtwarzacza. Wprowadzone tutaj zmiany nie są trwałe i nie są uwzględniane w zapytaniach do getPlaybackConfig(). Gdy zostanie wczytany następny element multimedialny, ten moduł obsługi zostanie wywołany ponownie.

Poniższy przykład pokazuje, jak ustawić PlaybackConfig podczas inicjowania CastReceiverContext. Konfiguracja zastępuje wychodzące żądania uzyskania plików manifestu. Obsługa określa, że żądania CORS Access-Control 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ć wartość PlaybackConfig za pomocą funkcji pobierającej i ustawiającej udostępnianych w PlayerManager. To ustawienie konfiguruje odtwarzacz tak, aby wznawiał 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ć wartość PlaybackConfig w przypadku konkretnej prośby o wczytanie za pomocą modułu obsługi informacji o odtwarzaniu multimediów. Procedura obsługi wywołuje metodę zaimplementowaną w aplikacjigetLicenseUrlForMedia, 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 Receiver SDK umożliwia aplikacji Web Receiver obsługę zdarzeń odtwarzacza. Detektor zdarzeń przyjmuje parametr cast.framework.events.EventType (lub tablicę tych parametrów), który określa zdarzenia, które powinny wywoływać detektor. Wstępnie skonfigurowane tablice cast.framework.events.EventType, które są przydatne do debugowania, znajdziesz w cast.framework.events.category. Parametr zdarzenia zawiera dodatkowe informacje o zdarzeniu.

Jeśli na przykład chcesz wiedzieć, kiedy jest emitowana zmiana mediaStatus, możesz użyć tej logiki do obsługi zdarzenia:

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 odbiornika internetowego przechwytywanie wiadomości i wykonywanie w nich niestandardowego kodu. Przechwytywacz wiadomości przyjmuje parametr cast.framework.messages.MessageType, który określa, jaki typ wiadomości ma być przechwytywany.

Interceptor powinien zwrócić zmodyfikowane żądanie lub obiekt Promise, który zwraca zmodyfikowaną wartość żądania. Zwrócenie wartości null uniemożliwi wywołanie domyślnego modułu obsługi wiadomości. Więcej informacji znajdziesz w artykule Wczytywanie multimediów.

Jeśli na przykład chcesz zmienić dane żądania wczytywania, możesz użyć 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 przechwytywaczu wiadomości wystąpią błędy, aplikacja odbiornika internetowego powinna zwrócić odpowiednie 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 kilka kluczowych różnic między przechwytywaniem wiadomości a detektorem zdarzeń:

  • Detektor zdarzeń nie umożliwia modyfikowania danych żądania.
  • Detektor zdarzeń najlepiej sprawdza się w przypadku uruchamiania analiz lub funkcji niestandardowej.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • Przechwytywanie wiadomości umożliwia nasłuchiwanie wiadomości, przechwytywanie ich i modyfikowanie danych żądania.
  • Przechwytywanie wiadomości najlepiej sprawdza się w przypadku obsługi niestandardowej logiki dotyczącej danych żądania.

Wczytuję multimedia

MediaInformation udostępnia wiele właściwości do wczytywania multimediów w wiadomości cast.framework.messages.MessageType.LOAD, w tym entity, contentUrl i contentId.

  • entity to sugerowana usługa do użycia we wdrożeniu zarówno w aplikacji nadawcy, jak i odbiorcy. Jest to adres URL precyzyjnego linku, który może być playlistą lub treścią multimedialną. Aplikacja powinna przeanalizować ten adres URL i wypełnić co najmniej jedno z pozostałych 2 pól.
  • Parametr contentUrl odpowiada adresowi URL, który odtwarzacz będzie używać do wczytywania treści. Na przykład ten adres URL może prowadzić do manifestu DASH.
  • Parametr contentId może być adresem URL treści, którą można odtworzyć (podobnym do adresu URL właściwości contentUrl), lub unikalnym identyfikatorem wczytywanych treści lub playlisty. Jeśli używasz tej właściwości jako identyfikatora, aplikacja powinna wypełnić adres URL z możliwością odtworzenia w polu contentUrl.

Zalecamy używanie parametru entity do przechowywania prawdziwego identyfikatora lub kluczowych parametrów, a parametru contentUrl do przechowywania adresu URL multimediów. Przykład tego znajdziesz w poniższym fragmencie kodu, w którym w żądaniu LOAD występuje parametr entity, a pobrany jest odtwarzalny element 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 zawiera informacje o podłączonym urządzeniu przesyłającym i urządzeniu wideo lub audio, które jest do niego podłączone. Metoda getDeviceCapabilities zawiera informacje o pomocy dotyczące Asystenta Google, Bluetootha oraz podłączonych wyświetlaczy i urządzeń audio.

Ta metoda zwraca obiekt, o który możesz wysłać zapytanie, przekazując jeden z określonych wyliczeń, aby uzyskać możliwość urządzenia dla tego wyliczenia. Wyliczenia są zdefiniowane w pliku cast.framework.system.DeviceCapabilities.

Ten przykład sprawdza, czy urządzenie Web Receiver może odtwarzać HDR i DolbyVision (DV) 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 interakcję z aplikacją odbiornika internetowego za pomocą aplikacji nadawcy (internetowych, na Androida i iOS), poleceń głosowych na urządzeniach z Asystentem, sterowania dotykowego na inteligentnych wyświetlaczach i pilotów na urządzeniach z Androidem TV. Pakiet Cast SDK udostępnia różne interfejsy API, które umożliwiają aplikacji odbiornika internetowego obsługę tych interakcji, aktualizowanie interfejsu aplikacji za pomocą stanów działań użytkownika i opcjonalne wysyłanie zmian w celu aktualizowania usług backendu.

Obsługiwane polecenia multimedialne

Stany elementów sterujących interfejsu są określane przez MediaStatus.supportedMediaCommands w przypadku rozwiniętych kontrolerów nadawców na iOS i Androida, aplikacji odbiornika i pilota działających na urządzeniach dotykowych oraz aplikacji odbiornika na urządzeniach z Androidem TV. Gdy w usłudze włączony jest określony bit Command, włączane są przyciski powiązane z tym działaniem. Jeśli wartość nie jest ustawiona, przycisk jest wyłączony. Wartości te można zmienić w odbiorniku internetowym, wykonując te czynności:

  1. Używanie PlayerManager.setSupportedMediaCommands do ustawiania konkretnego Commands
  2. Dodawanie nowego polecenia za pomocą addSupportedMediaCommands
  3. Usuwanie istniejącego polecenia za pomocą symbolu removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Gdy odbiorca przygotuje zaktualizowany MediaStatus, będzie on zawierać zmiany w usłudze supportedMediaCommands. Gdy stan jest transmitowany, połączone aplikacje wysyłające aktualizują odpowiednio przyciski w swoim interfejsie.

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

Zarządzanie stanami działań użytkownika

Gdy użytkownicy wchodzą w interakcję z interfejsem lub wysyłają polecenia głosowe, mogą sterować odtwarzaniem treści i właściwościami powiązanymi z odtwarzanym elementem. Żądania sterujące odtwarzaniem są obsługiwane automatycznie przez pakiet SDK. Żądania, które modyfikują właściwości aktualnie odtwarzanego elementu, takie jak polecenie LIKE, wymagają obsługi przez aplikację odbiornika. Pakiet SDK udostępnia serię interfejsów API do obsługi tych typów żądań. Aby spełnić te prośby, musisz wykonać te czynności:

  • Podczas wczytywania elementu multimedialnego ustaw wartość MediaInformation userActionStates zgodnie z preferencjami użytkownika.
  • Przechwytywanie wiadomości USER_ACTION i określanie żądanego działania.
  • Zaktualizuj MediaInformation UserActionState, aby zaktualizować interfejs.

Poniższy fragment kodu przechwytuje żądanie LOAD i wypełnia MediaInformation w LoadRequestData. 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;
    });

Poniższy fragment kodu przechwytuje wiadomość USER_ACTION i obsługuje wywoływanie backendu z żądaną zmianą. Następnie wywołuje funkcję aktualizacji UserActionState na urządzeniu odbiorcy.

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

Poniższy fragment kodu symuluje wywołanie usługi backendu. Funkcja sprawdza UserActionRequestData, aby określić typ zmiany, o którą prosi użytkownik, 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 wartość UserActionRequestData i dodaje lub usuwa z niej wartość UserActionState MediaInformation. Aktualizacja UserActionState w MediaInformation zmienia stan przycisku, który jest powiązany z żądanym działaniem. Ta zmiana jest widoczna w interfejsie sterowania inteligentnym wyświetlaczem, aplikacji do obsługi pilota i interfejsie Androida TV. Jest on też przesyłany w MediaStatuswiadomościach wychodzących, aby zaktualizować interfejs rozwiniętego kontrolera dla nadawców korzystających z 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

W pakiecie Web Receiver SDK na urządzenia z Asystentem obsługiwane są obecnie te polecenia multimedialne. Domyślne implementacje tych poleceń znajdują się w pliku cast.framework.PlayerManager.

Polecenie Opis
Google Play Odtwarzanie lub wznawianie odtwarzania po wstrzymaniu.
Wstrzymywanie Wstrzymaj odtwarzanie bieżących treści.
Wstecz Przejdź do poprzedniego elementu w kolejce multimediów.
Dalej Przejdź do następnego elementu w kolejce multimediów.
Zatrzymaj Zatrzymaj odtwarzane multimedia.
Powtórz – brak Wyłącz powtarzanie elementów multimedialnych w kolejce po zakończeniu odtwarzania ostatniego elementu w kolejce.
Powtórz 1 Powtarzaj aktualnie odtwarzane multimedia w nieskończoność.
Powtórz wszystko Powtórz wszystkie elementy w kolejce po odtworzeniu ostatniego z nich.
Powtórz wszystko i odtwarzaj losowo Gdy ostatni element w kolejce zostanie odtworzony, kolejka zostanie przetasowana i wszystkie elementy w kolejce zostaną odtworzone ponownie.
Odtwarzaj losowo Losowe odtwarzanie elementów multimedialnych w kolejce multimediów.
Napisy WŁ./WYŁ. Włączanie i wyłączanie napisów w multimediach. Włączanie i wyłączanie jest też dostępne w przypadku poszczególnych języków.
Przewiń do czasu bezwzględnego Przechodzi do określonego czasu bezwzględnego.
Przewiń do czasu względnego względem bieżącego czasu. Przesuwa odtwarzanie do przodu lub do tyłu o określony czas względem bieżącego czasu odtwarzania.
Zagraj ponownie Uruchom ponownie odtwarzane obecnie multimedia lub odtwórz ostatnio odtwarzany element, jeśli nic nie jest odtwarzane.
Ustawianie szybkości odtwarzania zmieniać szybkość odtwarzania multimediów, Powinno to być obsługiwane domyślnie. Możesz użyć interfejsu SET_PLAYBACK_RATE do przechwytywania wiadomości, aby zastępować przychodzące żądania stawek.

Obsługiwane polecenia multimedialne za pomocą głosu

Aby polecenie głosowe nie wywoływało polecenia multimedialnego na urządzeniu z Asystentem, musisz najpierw ustawić obsługiwane polecenia multimedialne, które chcesz obsługiwać. Następnie musisz wymusić te polecenia, włączając właściwość CastReceiverOptions.enforceSupportedCommands. Interfejs użytkownika na nadajnikach pakietu Cast SDK i urządzeniach z obsługą dotyku zmieni się, aby odzwierciedlać te konfiguracje. Jeśli flaga nie jest włączona, przychodzące polecenia głosowe będą wykonywane.

Jeśli np. zezwalasz na PAUSE z aplikacji wysyłających i urządzeń z obsługą dotykową, musisz też skonfigurować odbiornik, aby odzwierciedlał te ustawienia. Po skonfigurowaniu wszystkie przychodzące polecenia głosowe, które nie znajdują się na liście obsługiwanych poleceń, będą odrzucane.

W przykładzie poniżej podajemy CastReceiverOptions podczas uruchamiania CastReceiverContext. Dodaliśmy obsługę polecenia PAUSE i wymusiliśmy, aby odtwarzacz obsługiwał tylko to polecenie. Jeśli polecenie głosowe zażąda innej operacji, np. SEEK, zostanie odrzucone. Użytkownik zostanie powiadomiony, ż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ć osobną logikę w przypadku każdego polecenia, które chcesz ograniczyć. Usuń flagę enforceSupportedCommands i w przypadku każdego polecenia, które chcesz ograniczyć, możesz przechwycić wiadomość przychodzącą. W tym miejscu przechwytujemy żądanie dostarczone przez pakiet SDK, aby polecenia SEEK wydawane na urządzeniach z Asystentem nie powodowały przewijania w aplikacji Web Receiver.

W przypadku poleceń dotyczących multimediów, których aplikacja nie obsługuje, zwróć odpowiedni powód błędu, np. 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;
  });

Przechodzenie w tryb działania w tle na podstawie aktywności głosowej

Jeśli platforma Cast wyciszy dźwięk aplikacji w tle z powodu aktywności Asystenta, np. słuchania mowy użytkownika lub odpowiadania, do aplikacji odbiornika internetowego zostanie wysłana wiadomość FocusState NOT_IN_FOCUS, gdy aktywność się rozpocznie. Po zakończeniu aktywności wysyłana jest kolejna wiadomość z informacją IN_FOCUS. W zależności od aplikacji i odtwarzanych multimediów możesz chcieć wstrzymać odtwarzanie, gdy FocusState jest NOT_IN_FOCUS, przechwytując typ wiadomości FOCUS_STATE.

Na przykład dobrym rozwiązaniem jest wstrzymanie odtwarzania 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 określony głosowo

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

Na przykład w przypadku polecenia „OK Google, włącz napisy” wartość isSuggestedLanguage jest ustawiona na true, ponieważ język został określony na podstawie języka, w którym zostało wypowiedziane polecenie. Jeśli język jest wyraźnie określony w żądaniu, np. „OK Google, włącz napisy w języku angielskim”, wartość isSuggestedLanguage jest ustawiona na false.

Metadane i dubbing

Domyślnie polecenia głosowe są obsługiwane przez odbiornik internetowy, ale musisz zadbać o to, aby metadane treści były kompletne i dokładne. Dzięki temu Asystent będzie prawidłowo obsługiwać polecenia głosowe, a metadane będą się poprawnie wyświetlać w nowych typach interfejsów, takich jak aplikacja Google Home i wyświetlacze inteligentne, np. Google Home Hub.

Przesyłanie strumieniowe

Zachowanie stanu sesji jest podstawą przenoszenia strumienia, dzięki któremu użytkownicy mogą przenosić istniejące strumienie audio i wideo między urządzeniami za pomocą poleceń głosowych, aplikacji Google Home lub inteligentnych wyświetlaczy. Odtwarzanie multimediów zatrzymuje się na jednym urządzeniu (źródłowym) i jest kontynuowane na innym (docelowym). Każde urządzenie Cast z najnowszym oprogramowaniem może być źródłem lub miejscem docelowym podczas przesyłania strumieniowego.

Przepływ zdarzeń w przypadku przesyłania strumieniowego jest następujący:

  1. Na urządzeniu źródłowym:
    1. Odtwarzanie multimediów zostanie zatrzymane.
    2. Aplikacja odbiornika internetowego otrzymuje polecenie zapisania bieżącego stanu multimediów.
    3. Aplikacja Web Receiver zostanie wyłączona.
  2. Na urządzeniu docelowym:
    1. Aplikacja odbiornika internetowego jest wczytywana.
    2. Aplikacja odbiornika internetowego otrzymuje polecenie przywrócenia zapisanego stanu multimediów.
    3. Odtwarzanie multimediów zostanie wznowione.

Elementy stanu multimediów:

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

Włączanie przesyłania strumieniowego

Aby wdrożyć przeniesienie odtwarzania w odbiorniku internetowym:

  1. Zaktualizuj supportedMediaCommands za pomocą polecenia STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. Opcjonalnie możesz zastąpić interfejsy SESSION_STATE i RESUME_SESSION, jak opisano w sekcji Zachowywanie stanu sesji. Zastąp je tylko wtedy, gdy dane niestandardowe mają być przechowywane jako część migawki sesji. W przeciwnym razie domyślna implementacja zachowywania stanów sesji będzie obsługiwać przeniesienie odtwarzania.

Zachowywanie stanu sesji

Pakiet Web Receiver SDK udostępnia domyślną implementację aplikacji Web Receiver, która umożliwia zachowywanie stanów sesji przez tworzenie zrzutu bieżącego stanu multimediów, przekształcanie stanu w żądanie wczytania i wznawianie sesji za pomocą żądania wczytania.

W razie potrzeby żądanie wczytania wygenerowane przez odbiornik internetowy można zastąpić w SESSION_STATEprzechwytywaczu wiadomości. Jeśli chcesz dodać do żądania wczytania dane niestandardowe, umieść je w elemencie 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 RESUME_SESSION przechwytującym wiadomości.

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 ładowanie treści

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

Operacja wstępnego wczytywania wstępnie pobiera kilka segmentów nadchodzących elementów. Specyfikacja jest wykonywana na podstawie wartości preloadTime w obiekcie QueueItem (jeśli nie zostanie podana, domyślnie przyjmuje się wartość 20 sekund). Czas jest wyrażony w sekundach w odniesieniu do końca aktualnie odtwarzanego elementu . Dozwolone są tylko wartości dodatnie. Jeśli na przykład wartość wynosi 10 sekund, ten element zostanie wstępnie wczytany 10 sekund przed zakończeniem poprzedniego elementu. Jeśli czas wstępnego wczytywania jest dłuższy niż czas pozostały do końca currentItem, wstępne wczytywanie rozpocznie się tak szybko, jak to możliwe. Jeśli w przypadku elementu queueItem zostanie określona bardzo duża wartość wstępnego wczytywania, można uzyskać efekt polegający na tym, że podczas odtwarzania bieżącego elementu wstępnie wczytujemy już następny element. Jednak pozostawiamy to ustawienie i wybór deweloperowi, ponieważ ta wartość może wpływać na przepustowość i wydajność przesyłania strumieniowego aktualnie odtwarzanego elementu.

Wstępne wczytywanie będzie domyślnie działać w przypadku treści HLS, DASH i Smooth Streaming.

Zwykłe pliki wideo MP4 i audio, takie jak MP3, nie będą wstępnie wczytywane, ponieważ urządzenia Cast obsługują tylko 1 element multimedialny i nie można ich używać do wstępnego wczytywania, gdy odtwarzany jest już element treści.

Komunikaty niestandardowe

Wymiana wiadomości to podstawowa metoda interakcji w przypadku aplikacji odbiornika internetowego.

Nadawca wysyła wiadomości do odbiornika internetowego za pomocą interfejsów API nadawcy dla platformy, na której działa nadawca (Android, iOS, internet). Obiekt zdarzenia (który jest przejawem wiadomości) przekazywany do odbiorników zdarzeń ma element danych (event.data), w którym dane przyjmują właściwości określonego typu zdarzenia.

Aplikacja odbiornika internetowego może nasłuchiwać wiadomości w określonej przestrzeni nazw. Dzięki temu aplikacja odbiornika internetowego obsługuje protokół tej przestrzeni nazw. Następnie każdy połączony nadawca, który chce komunikować się w tej przestrzeni nazw, musi użyć odpowiedniego protokołu.

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

Oto fragment kodu odbiornika internetowego, który umożliwia 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 przypadku CastReceiverContext. Odbiornik internetowy może wysyłać wiadomości do poszczególnych nadawców w odpowiedzi na otrzymaną wiadomość lub w wyniku zmiany stanu aplikacji. Oprócz przesyłania wiadomości między dwoma punktami (z limitem 64 KB) odbiornik internetowy może też przesyłać wiadomości do wszystkich połączonych nadawców.

Przesyłanie na urządzenia audio

Więcej informacji o odtwarzaniu dźwięku znajdziesz w przewodniku po Google Cast dla urządzeń audio.

Android TV

W tej sekcji omawiamy, jak odbiornik internetowy Google wykorzystuje Twoje dane wejściowe do odtwarzania oraz 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 elementów sterujących urządzenia (np. pilota) na komunikaty odtwarzania multimediów zdefiniowane w przestrzeni nazw urn:x-cast:com.google.cast.media, zgodnie z opisem w sekcji Komunikaty odtwarzania multimediów. Aplikacja musi obsługiwać te wiadomości, aby sterować odtwarzaniem multimediów i umożliwiać podstawowe sterowanie odtwarzaniem za pomocą elementów sterujących Androida TV.

Wytyczne dotyczące zgodności z Androidem TV

Oto kilka zaleceń i częstych błędów, których należy unikać, aby aplikacja była zgodna z Androidem TV:

  • Pamiętaj, że ciąg tekstowy agenta użytkownika zawiera zarówno „Android”, jak i „CrKey”. Niektóre witryny mogą przekierowywać użytkowników do witryny przeznaczonej tylko na urządzenia mobilne, ponieważ wykrywają etykietę „Android”. Nie zakładaj, że „Android” w ciągu znaków klienta użytkownika zawsze oznacza użytkownika mobilnego.
  • Stos multimedialny Androida może używać transparentnego GZIP do pobierania danych. Upewnij się, że dane multimedialne mogą odpowiadać na Accept-Encoding: gzip.
  • Zdarzenia multimedialne HTML5 na Androidzie TV mogą być wywoływane w innych momentach niż na urządzeniach Chromecast. Może to ujawnić problemy, które były ukryte na urządzeniach Chromecast.
  • Podczas 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ż zwykle zależą one od platformy. Więcej informacji o obsłudze zdarzeń multimedialnych w odbiorniku znajdziesz w artykule Zdarzenia multimedialne.
  • Podczas konfigurowania certyfikatów HTTPS witryny odbiorcy pamiętaj o uwzględnieniu certyfikatów pośrednich urzędu certyfikacji. Na stronie testowej SSL Qualsys możesz sprawdzić, czy zaufana ścieżka certyfikacji Twojej witryny zawiera certyfikat urzędu certyfikacji oznaczony jako „dodatkowe pobieranie”. Jeśli tak jest, witryna może nie wczytywać się na platformach opartych na Androidzie.
  • Chromecast wyświetla stronę odbiornika na płaszczyźnie graficznej 720p, a inne platformy Cast, w tym Android TV, mogą wyświetlać stronę w rozdzielczości do 1080p. Upewnij się, że strona odbiorcy dobrze się skaluje w różnych rozdzielczościach.