1. Opis
Dzięki tym ćwiczeniom z programowania dowiesz się, jak utworzyć aplikację niestandardowego odbiornika internetowego do odtwarzania treści na urządzeniach obsługujących Cast.
Co to jest Google Cast?
Google Cast pozwala użytkownikom przesyłać treści z urządzenia mobilnego na telewizor. Użytkownicy mogą wtedy używać urządzeń mobilnych lub przeglądarki Chrome na komputerze jako pilota do odtwarzania multimediów na telewizorze.
Pakiet SDK Google Cast umożliwia aplikacji sterowanie urządzeniami obsługującymi Google Cast (np. telewizorem czy systemem audio). Pakiet SDK Cast udostępnia niezbędne komponenty interfejsu, które są zgodne z listą kontrolną projektowania Google Cast.
Dostępna jest lista kontrolna projektu Google Cast, dzięki której korzystanie z Cast jest proste i przewidywalne na wszystkich obsługiwanych platformach. Więcej informacji
Co będziemy tworzyć?
Po ukończeniu tego ćwiczenia z programowania będziesz mieć aplikację HTML5, która będzie działać jako Twój własny niestandardowy odbiornik umożliwiający wyświetlanie treści wideo na urządzeniach obsługujących Cast.
Czego się nauczysz
- Jak przygotować się do programowania odbiorników.
- Podstawowe informacje o odbiorniku obsługującym Cast, opartym na platformie Cast Application Framework.
- Jak odebrać film, który będzie przesyłany.
- Jak zintegrować Rejestrator debugowania.
- Jak zoptymalizować odbiornik pod kątem inteligentnych ekranów.
Czego potrzebujesz
- najnowszą przeglądarkę Google Chrome,
- usługa hostingu HTTPS, na przykład Firebase Hosting lub ngrok;
- Urządzenie przesyłające Google Cast, takie jak Chromecast czy Android TV, z dostępem do internetu.
- Telewizor lub monitor z wejściem HDMI.
Funkcja
- Aby skorzystać z tej możliwości, musisz mieć wiedzę w zakresie tworzenia stron internetowych.
- Potrzebna będzie też wcześniejsza wiedza o oglądaniu telewizji :)
Jak będziesz korzystać z tego samouczka?
Jak oceniasz swoje doświadczenia z tworzeniem aplikacji internetowych?
Jak oceniasz swoje wrażenia z oglądania telewizji?
2. Pobieranie przykładowego kodu
Możesz pobrać cały przykładowy kod na komputer...
i rozpakuj pobrany plik ZIP.
3. Lokalne wdrażanie odbiornika
Aby można było używać odbiornika internetowego z urządzeniem przesyłającym, musi on być hostowany w miejscu, w którym urządzenie przesyłające ma do niego dostęp. Jeśli masz już serwer obsługujący https, pomiń poniższe instrukcje i zanotuj adres URL, ponieważ będzie on potrzebny w następnej sekcji.
Jeśli nie masz serwera, którego można użyć, możesz użyć Hostingu Firebase lub ngrok.
Uruchamianie serwera
Po skonfigurowaniu wybranej usługi przejdź do app-start
i uruchom serwer.
Zanotuj adres URL hostowanego odbiornika. Użyjesz go w następnej sekcji.
4. Rejestrowanie aplikacji w Konsoli programisty Cast
Aby móc uruchamiać niestandardowy odbiornik (wbudowany w te ćwiczenia z programowania) na urządzeniach Chromecast, musisz zarejestrować swoją aplikację. Po zarejestrowaniu aplikacji otrzymasz identyfikator, którego aplikacja musi używać do wykonywania wywołań interfejsu API, na przykład do uruchamiania aplikacji odbierającej.
Kliknij „Dodaj nową aplikację”
Wybierz „Odbiornik niestandardowy”. To właśnie nad tym pracujemy.
Wpisz dane nowego odbiorcy. Pamiętaj, aby użyć docelowego adresu URL.
w ostatniej sekcji. Zanotuj identyfikator aplikacji przypisany do nowego odbiornika.
Musisz też zarejestrować urządzenie Google Cast, by mogło mieć dostęp do aplikacji odbierającej przed jej opublikowaniem. Po opublikowaniu aplikacji odbierającej będzie ona dostępna dla wszystkich urządzeń Google Cast. Na potrzeby tych ćwiczeń z programowania zalecamy pracę z nieopublikowaną aplikacją odbierającą.
Kliknij „Dodaj nowe urządzenie”.
Wpisz numer seryjny wydrukowany z tyłu urządzenia Cast i nadaj mu opisową nazwę. Numer seryjny możesz też znaleźć, przesyłając ekran w Chrome, gdy otworzysz Google Cast SDK Developer Console.
Zanim odbiornik i urządzenie będą gotowe do testowania, może minąć 5–15 minut. Po 5–15 minutach musisz zrestartować urządzenie przesyłające.
5. Uruchamianie przykładowej aplikacji
Czekając, aż nowa aplikacja odbierająca będzie gotowa do testów, zobaczmy, jak wygląda przykładowa ukończona aplikacja odbierająca. Odbiornik, który stworzymy, będzie w stanie odtwarzać multimedia z wykorzystaniem przesyłania strumieniowego z adaptacyjną szybkością transmisji bitów (użyjemy przykładowej treści zakodowanej na potrzeby dynamicznego przesyłania strumieniowego przez HTTP (DASH).
W przeglądarce otwórz narzędzie Command and Control (CaC).
- Powinno być widoczne nasze narzędzie do zarządzania relacjami z klientami (CAC).
- Użyj domyślnego przykładowego identyfikatora odbiornika „CC1AD845” i kliknij przycisk „Ustaw identyfikator aplikacji”.
- Kliknij przycisk Cast w lewym górnym rogu i wybierz urządzenie Google Cast.
- Przejdź do karty „Wczytaj multimedia” u góry.
- Kliknij przycisk „Wczytaj według treści”, aby odtworzyć przykładowy film.
- Film zacznie się odtwarzać na urządzeniu Google Cast, aby pokazać, jak wygląda podstawowy odbiornik w przypadku domyślnego odbiornika.
6. Przygotuj projekt początkowy
Musimy dodać obsługę Google Cast do pobranej aplikacji startowej. Oto niektóre z terminologii związanej z Google Cast, których będziemy używać w tym ćwiczeniu z programowania:
- aplikacja nadawca działa na urządzeniu mobilnym lub laptopie,
- aplikacja odbiornika działa na urządzeniu Google Cast;
Możesz teraz zacząć pracować nad projektem początkowym za pomocą ulubionego edytora tekstu:
- Wybierz katalog
app-start
z pobranego przykładowego kodu. - Otwórz
js/receiver.js
iindex.html
Podczas wykonywania tych ćwiczeń z programowania http-server
powinien wykrywać wprowadzone przez Ciebie zmiany. Jeśli zauważysz, że nie, wyłącz i ponownie uruchom aplikację http-server
.
Projektowanie aplikacji
Aplikacja odbierająca inicjuje sesję przesyłania i pozostaje w trybie gotowości, dopóki nie nadejdzie żądanie WCZYTUJĘ (czyli polecenie odtwarzania multimediów).
Aplikacja składa się z 1 widoku głównego zdefiniowanego w index.html
i 1 pliku JavaScript o nazwie js/receiver.js
, który zawiera wszystkie funkcje logiczne niezbędne do działania odbiornika.
index.html
Ten plik HTML będzie zawierać interfejs naszej aplikacji odbierającej. Na razie jest pusty, ale w trakcie ćwiczenia z kodowania będziemy go dodawać.
receiver.js
Ten skrypt będzie zarządzać całą logiką naszej aplikacji odbierającej. Na razie jest to po prostu pusty plik, ale w następnej sekcji zmienimy go w w pełni działający odbiornik Cast.
7. Podstawowy odbiornik
Podstawowy odbiornik zainicjuje sesję przesyłania podczas uruchamiania. Jest to konieczne, aby poinformować wszystkie połączone aplikacje nadawcy, że uruchomienie odbiorcy zakończyło się powodzeniem. Poza tym nowy pakiet SDK jest wstępnie skonfigurowany do obsługi multimediów strumieniowanych z adaptacyjną szybkością transmisji bitów (z użyciem DASH, HLS i Smooth Streaming) oraz zwykłych plików MP4. Spróbujmy.
Inicjacja
Dodaj ten kod do elementu index.html
w nagłówku:
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>
Dodaj poniższy kod do kodu index.html
<body>
przed elementem <footer>
załadowaniem receiver.js,
, aby zapewnić pakietowi SDK odbiorcy miejsce na wyświetlenie domyślnego interfejsu odbiorcy, który jest wysyłany ze dodanym właśnie skryptem.
<cast-media-player></cast-media-player>
Teraz musimy zainicjować pakiet SDK w js/receiver.js
, w skład którego wchodzą:
- uzyskanie odniesienia do
CastReceiverContext
, podstawowego punktu wejścia do całego pakietu SDK odbiornika; - przechowywanie odniesień do
PlayerManager
, czyli obiektu obsługującego odtwarzanie i zapewniania wszystkich punktów zaczepienia potrzebnych do obsługi własnej logiki; - inicjowanie pakietu SDK przez wywołanie
start()
w systemieCastReceiverContext
Dodaj te elementy do grupy reklam js/receiver.js
.
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
context.start();
8. Przesyłanie „podstawowych” treści wideo
Na potrzeby tego ćwiczenia z programowania użyj narzędzia CaC, aby wypróbować nowy odbiornik.
Otwórz w przeglądarce narzędzie Command and Control (CaC).
Zastąp własny identyfikator aplikacji zarejestrowanym wcześniej w polu i kliknij „Ustaw identyfikator aplikacji”. Dzięki temu narzędzie będzie używać odbiornika po rozpoczęciu sesji przesyłania.
Przesyłanie multimediów
Ogólnie, aby odtwarzać multimedia na urządzeniu przesyłającym, musisz wykonać te czynności:
- Nadawca tworzy z pakietu SDK Cast obiekt
MediaInfo
JSON
, który modeluje element multimedialny. - Nadawca łączy się z urządzeniem Cast, by uruchomić aplikację odbiorcy.
- Odbiorca wczytuje obiekt
MediaInfo
za pomocą żądaniaLOAD
, aby odtworzyć treść. - Odbiornik monitoruje i śledzi stan multimediów.
- Nadawca wysyła do odbiorcy polecenia odtwarzania, aby kontrolować odtwarzanie na podstawie interakcji użytkownika z aplikacją nadawcy.
W ramach pierwszej podstawowej próby uzupełnimy MediaInfo
adresem URL zasobu możliwego do odtworzenia (zapisany w: MediaInfo.contentUrl
).
Rzeczywisty nadawca używa w MediaInfo.contentId
identyfikatora multimediów specyficznego dla aplikacji. Odbiorca używa contentId
jako identyfikatora do wykonywania odpowiednich wywołań interfejsu API backendu w celu rozpoznania rzeczywistego adresu URL zasobu i ustawiania go na MediaInfo.contentUrl.
. Adresat będzie też mógł wykonywać zadania takie jak pozyskiwanie licencji DRM czy wstawianie informacji o przerwach na reklamę.
W następnej sekcji rozszerzymy zakres odbiorcy, aby robił to samo co Ty. Na razie kliknij ikonę Cast i wybierz urządzenie, aby otworzyć odbiornik.
Przejdź do karty „Wczytaj multimedia” i kliknij przycisk „Wczytaj według treści”. Odbiornik powinien rozpocząć odtwarzanie przykładowej treści.
Pakiet SDK odbiornika udostępnia gotowe do użycia funkcje:
- Inicjuję sesję przesyłania
- Obsługuj przychodzące żądania
LOAD
od nadawców, które zawierają zasoby możliwe do odtworzenia - Udostępnij podstawowy interfejs odtwarzacza gotowy do wyświetlania na dużym ekranie.
Zapoznaj się z narzędziem CaC i jego kodem, zanim przejdziemy do kolejnej sekcji, w której rozszerzymy adresata do rozmowy z prostym przykładowym interfejsem API, aby zrealizować przychodzące żądania LOAD
od nadawców.
9. Integracja z zewnętrznym interfejsem API
Zgodnie ze sposobem, w jaki większość deweloperów korzysta z odbiorników przesyłania w rzeczywistych aplikacjach, zmienimy nasz odbiornik tak, aby obsługiwał żądania LOAD
, które odwołują się do odpowiednich treści multimedialnych za pomocą klucza API, zamiast wysyłać adres URL zasobu z możliwością odtworzenia.
Dzieje się tak zwykle, ponieważ:
- Nadawca może nie znać adresu URL treści.
- Aplikacja Cast została zaprojektowana do obsługi uwierzytelniania, innych logiki biznesowej lub wywołań interfejsu API bezpośrednio na odbiorniku.
Ta funkcja jest wdrażana głównie w metodzie PlayerManager
setMessageInterceptor()
. Dzięki temu możesz przechwytywać wiadomości przychodzące według typu i modyfikować je, zanim dotrą do wewnętrznego modułu obsługi wiadomości pakietu SDK. W tej sekcji omawiamy żądania (LOAD
), w przypadku których:
- Odczytaj przychodzące żądanie
LOAD
i jego niestandardowe żądaniecontentId
. - Wykonaj wywołanie
GET
do naszego interfejsu API, aby wyszukać zasób możliwy do strumieniowego przesyłania według jego atrybutucontentId
. - Zmodyfikuj żądanie
LOAD
, używając adresu URL strumienia. - Aby ustawić parametry typu strumienia, zmodyfikuj obiekt
MediaInformation
. - Przekaż żądanie do SDK w celu odtworzenia lub odrzuć to polecenie, jeśli nie można znaleźć żądanych multimediów.
Udostępniony przykładowy interfejs API prezentuje punkty zaczepienia pakietu SDK do dostosowywania typowych zadań odbiorcy, nadal polegając w większości na gotowych rozwiązaniach.
Przykładowy interfejs API
Wpisz w przeglądarce adres https://storage.googleapis.com/cpe-sample-media/content.json i zapoznaj się z naszym przykładowym katalogiem filmów. Zawartość obejmuje adresy URL obrazów plakatów w formacie PNG oraz strumienie DASH i HLS. Strumienie DASH i HLS wskazują zdemiksowane źródła wideo i audio przechowywane w pofragmentowanych kontenerach mp4.
{
"bbb": {
"author": "The Blender Project",
"description": "Grumpy Bunny is grumpy",
"poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
"stream": {
"dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
"hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
"title": "Big Buck Bunny"
},
"fbb_ad": {
"author": "Google Inc.",
"description": "Introducing Chromecast. The easiest way to enjoy [...]",
"poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
"stream": {
"dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
"hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
"title": "For Bigger Blazes"
},
[...]
}
W następnym kroku zmapujemy klucz każdego wpisu (na przykład bbb, fbb_ad
) na adres URL strumienia po wywołaniu odbiornika za pomocą żądania LOAD
.
Przechwytywanie żądania LOAD
W tym kroku utworzymy obiekt przechwytujący obciążenie z funkcją, która wysyła żądanie XHR
do hostowanego pliku JSON
. Po uzyskaniu pliku JSON
przeanalizujemy treść i ustawimy metadane. W kolejnych sekcjach dostosujemy parametry MediaInformation
, aby określić typ treści.
Dodaj ten kod do pliku js/receiver.js
tuż przed wywołaniem funkcji context.start()
.
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
let xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(JSON.parse(xhr.response));
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
reject();
} else {
// Add metadata
let metadata = new
cast.framework.messages.GenericMediaMetadata();
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
W następnej sekcji opisujemy, jak skonfigurować właściwość media
żądania wczytania na potrzeby treści DASH.
Korzystanie z przykładowej treści DASH interfejsu API
Po przygotowaniu modułu do przechwytywania obciążenia określimy typ treści w odbiorniku. Na podstawie tych informacji odbiorca otrzyma adres URL playlisty reklamy nadrzędnej oraz typ MIME strumienia. Dodaj ten kod do pliku js/receiver.js w elemenciePromise()
przechwytującego LOAD
:
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
...
}
});
});
});
Po wykonaniu tego kroku możesz przejść do testowania, aby spróbować wczytać treści z treścią DASH. Jeśli zamiast tego chcesz przetestować wczytywanie za pomocą treści HLS, przejdź do następnego kroku.
Korzystanie z przykładowej treści HLS interfejsu API
Przykładowy interfejs API zawiera treści HLS i DASH. Oprócz skonfigurowania ustawienia contentType
tak jak w poprzednim kroku, żądanie wczytania wymaga pewnych dodatkowych właściwości, by można było korzystać z adresów URL HLS przykładowego interfejsu API. Gdy odbiornik jest skonfigurowany do odtwarzania strumieni HLS, domyślnym oczekiwanym typem kontenera jest strumień transportu (TS). W efekcie odbiornik spróbuje otworzyć przykładowe strumienie MP4 w formacie TS, jeśli zmieni się tylko właściwość contentUrl
. W żądaniu wczytania obiekt MediaInformation
należy zmodyfikować za pomocą dodatkowych właściwości, aby odbiorca wiedział, że treść jest typu MP4, a nie TS. Aby zmodyfikować właściwości contentUrl
i contentType
, dodaj ten kod do pliku js/receiver.js w programie przechwytującym obciążenie. Dodaj też właściwości HlsSegmentFormat
i HlsVideoSegmentFormat
.
...
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
return new Promise((resolve, reject) => {
...
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.hls;
request.media.contentType = 'application/x-mpegurl';
request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
...
}
});
});
});
Testowanie
Ponownie otwórz narzędzie Command and Control (CaC) i ustaw identyfikator aplikacji jako identyfikator aplikacji odbiorcy. Wybierz urządzenie, klikając przycisk Cast.
Przejdź do karty „Wczytaj multimedia”. Tym razem usuń tekst w polu „Adres URL treści” obok przycisku „Wczytaj według treści”, co zmusi naszą aplikację do wysłania żądania LOAD
zawierającego tylko odwołanie do contentId
naszych multimediów.
Zakładając, że po zmodyfikowaniu odbiornika wszystko działa prawidłowo, moduł przechwytujący powinien kształtować obiekt MediaInfo
w coś, co SDK może odtwarzać na ekranie.
Aby sprawdzić, czy multimedia są odtwarzane prawidłowo, kliknij przycisk „Wczytaj według zawartości”. Możesz zmienić identyfikator treści na inny w pliku content.json.
10. Optymalizacja pod kątem inteligentnych ekranów
Inteligentne ekrany to urządzenia z funkcjami dotykowymi, które umożliwiają aplikacjom odbierającym obsługę sterowania dotykowego.
W tej sekcji dowiesz się, jak zoptymalizować aplikację odbiornika po uruchomieniu na inteligentnych ekranach oraz jak dostosować elementy sterujące odtwarzaczem.
Uzyskiwanie dostępu do elementów sterujących interfejsu
Dostęp do obiektów elementów sterujących interfejsu na inteligentnych ekranach można uzyskać, używając aplikacji cast.framework.ui.Controls.GetInstance()
. Dodaj ten kod do pliku js/receiver.js
powyżej context.start()
:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
context.start();
Jeśli nie używasz elementu <cast-media-player>, musisz ustawić touchScreenOptimizedApp
w elemencie CastReceiverOptions
. W tym ćwiczeniu z programowania korzystamy z elementu <cast-media-player>.
context.start({ touchScreenOptimizedApp: true });
Domyślne przyciski sterujące są przypisywane do poszczególnych boksów na podstawie MetadataType
i MediaStatus.supportedMediaCommands
.
Sterowanie odtwarzaniem
W aplikacjach MetadataType.MOVIE
, MetadataType.TV_SHOW
i MetadataType.GENERIC
obiekt elementów sterujących interfejsu użytkownika na inteligentnych ekranach będzie wyświetlany, jak widać w poniższym przykładzie.
--playback-logo-image
MediaMetadata.subtitle
MediaMetadata.title
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.QUEUE_PREV
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.SEEK_BACKWARD_30
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.SEEK_FORWARD_30
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.QUEUE_NEXT
Elementy sterujące dźwiękiem
W przypadku MetadataType.MUSIC_TRACK
obiekt elementów sterujących interfejsu na inteligentnych ekranach będzie wyświetlany w ten sposób:
--playback-logo-image
MusicTrackMediaMetadata.albumName
MusicTrackMediaMetadata.title
MusicTrackMediaMetadata.albumArtist
MusicTrackMediaMetadata.images[0]
MediaStatus.currentTime
MediaInformation.duration
ControlsSlot.SLOT_SECONDARY_1
:ControlsButton.NO_BUTTON
ControlsSlot.SLOT_PRIMARY_1
:ControlsButton.QUEUE_PREV
PLAY/PAUSE
ControlsSlot.SLOT_PRIMARY_2
:ControlsButton.QUEUE_NEXT
ControlsSlot.SLOT_SECONDARY_2
:ControlsButton.NO_BUTTON
Aktualizowanie obsługiwanych poleceń multimedialnych
Obiekt elementów sterujących interfejsu określa też, czy wyświetlany jest ControlsButton
na podstawie MediaStatus.supportedMediaCommands
.
Gdy wartość supportedMediaCommands
jest równa ALL_BASIC_MEDIA
, domyślny układ elementu sterującego wygląda tak:
Gdy wartość supportedMediaCommands
jest równa ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT
, domyślny układ elementu sterującego wygląda tak:
Gdy wartość obsługiwanychMediaCommands wynosi PAUSE | QUEUE_PREV | QUEUE_NEXT
, domyślny układ elementu sterującego wygląda tak:
Jeśli ścieżki tekstowe są dostępne, przycisk napisów będzie zawsze wyświetlany na pozycji SLOT_1
.
Aby dynamicznie zmieniać wartość supportedMediaCommands
po uruchomieniu kontekstu odbiorcy, możesz wywołać PlayerManager.setSupportedMediaCommands
w celu zastąpienia wartości. Możesz też dodać nowe polecenie addSupportedMediaCommands
lub usunąć istniejące, używając polecenia removeSupportedMediaCommands
.
Dostosowywanie przycisków sterujących
Opcje możesz dostosować za pomocą PlayerDataBinder
. Dodaj ten kod do pliku js/receiver.js
pod elementami dotykowymi, aby ustawić pierwsze miejsce na elementy sterujące:
...
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
// Clear default buttons and re-assign
touchControls.clearDefaultSlotAssignments();
touchControls.assignButton(
cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
);
});
context.start();
11. Wdrażanie przeglądania multimediów na inteligentnych ekranach
Przeglądanie multimediów to funkcja odbiornika CAF, która pozwala użytkownikom odkrywać dodatkowe treści na urządzeniach dotykowych. W tym celu trzeba użyć PlayerDataBinder
do skonfigurowania interfejsu użytkownika BrowseContent
. Następnie możesz wypełnić go wartością BrowseItems
w zależności od treści, które chcesz wyświetlać.
BrowseContent
Poniżej znajdziesz przykład interfejsu użytkownika BrowseContent
i jego właściwości:
BrowseContent.title
BrowseContent.items
Format obrazu
Aby wybrać najlepszy współczynnik proporcji dla komponentów z obrazem, użyj pola targetAspectRatio property
. Pakiet SDK odbiornika CAF obsługuje 3 formaty obrazu: SQUARE_1_TO_1
, PORTRAIT_2_TO_3
oraz LANDSCAPE_16_TO_9
.
BrowseItem
Użyj parametru BrowseItem
, aby wyświetlić tytuł, podtytuł, czas trwania i obraz każdego elementu:
BrowseItem.image
BrowseItem.duration
BrowseItem.title
BrowseItem.subtitle
Ustaw dane przeglądania multimediów
Możesz udostępnić listę treści multimedialnych do przeglądania, dzwoniąc pod numer setBrowseContent
. Dodaj ten kod do pliku js/receiver.js
poniżej elementu playerDataBinder
i w detektorze zdarzeń MEDIA_CHANGED
, aby określić elementy przeglądania za pomocą tytułu „Następny”.
// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);
...
let browseItems = getBrowseItems();
function getBrowseItems() {
let browseItems = [];
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
for (let key in data) {
let item = new cast.framework.ui.BrowseItem();
item.entity = key;
item.title = data[key].title;
item.subtitle = data[key].description;
item.image = new cast.framework.messages.Image(data[key].poster);
item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
browseItems.push(item);
}
});
return browseItems;
}
let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;
playerDataBinder.addEventListener(
cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
(e) => {
if (!e.value) return;
....
// Media browse
touchControls.setBrowseContent(browseContent);
});
Kliknięcie elementu przeglądania multimediów wywoła przechwytywanie LOAD
. Dodaj ten kod do elementu przechwytującego LOAD
, aby zmapować obiekt request.media.contentId
na element request.media.entity
z elementu przeglądania multimediów:
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
...
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
...
});
});
Możesz też ustawić obiekt BrowseContent
na null
, aby usunąć interfejs przeglądania multimediów.
12. Debugowanie aplikacji odbierających
Pakiet Cast pickupr SDK to inna opcja dla programistów, która pozwala łatwo debugować aplikacje odbiornika za pomocą interfejsu CastDebugLogger API i powiązanego z nim narzędzia Command and Control (CaC) do przechwytywania dzienników.
Zdarzenie inicjujące
Aby zastosować interfejs API, dodaj skrypt źródłowy CastDebugLogger
w pliku index.html. Źródło powinno być zadeklarowane w tagu <head> po zadeklarowaniu pakietu SDK Cast Odbieranie.
<head>
...
<script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
<!-- Cast Debug Logger -->
<script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>
W js/receiver.js
na górze pliku i pod playerManager
dodaj ten kod, aby pobrać wystąpienie CastDebugLogger
i włączyć rejestrator:
const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
Gdy rejestrator debugowania jest włączony, na odbiorniku pojawi się nakładka z tekstem DEBUG MODE
.
Zdarzenia odtwarzacza dziennika
Za pomocą CastDebugLogger
możesz łatwo rejestrować zdarzenia odtwarzacza, które są uruchamiane przez pakiet SDK odbiornika CAF, a także rejestrować dane zdarzeń za pomocą różnych poziomów rejestratora. Konfiguracja loggerLevelByEvents
używa elementów cast.framework.events.EventType
i cast.framework.events.category
do określania, które zdarzenia będą rejestrowane.
Dodaj ten kod pod deklaracją castDebugLogger
, aby zapisywać informacje o wywołaniu zdarzenia CORE
odtwarzacza lub przekazaniu zmiany mediaStatus
:
// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
castDebugLogger.setEnabled(true);
}
});
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
Komunikaty logu i tagi niestandardowe
Interfejs CastDebugLogger API umożliwia tworzenie komunikatów dziennika w różnych kolorach, które są wyświetlane na nakładce debugowania odbiornika. Dostępne są te metody rejestrowania, uporządkowane w kolejności od najwyższego do najniższego priorytetu:
castDebugLogger.error(custom_tag, message);
castDebugLogger.warn(custom_tag, message);
castDebugLogger.info(custom_tag, message);
castDebugLogger.debug(custom_tag, message);
W przypadku każdej metody rejestrowania pierwszym parametrem jest tag niestandardowy. Może to być dowolny ciąg identyfikujący Cię, który uznasz za ważny. CastDebugLogger
używa tagów do filtrowania logów. Zastosowanie tagów zostało szczegółowo wyjaśnione poniżej. Drugi parametr to komunikat logu.
Aby pokazać logi w działaniu, dodaj logi do przechwytywania LOAD
.
playerManager.setMessageInterceptor(
cast.framework.messages.MessageType.LOAD,
request => {
castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');
// Map contentId to entity
if (request.media && request.media.entity) {
request.media.contentId = request.media.entity;
}
return new Promise((resolve, reject) => {
// Fetch content repository by requested contentId
makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
.then(function (data) {
let item = data[request.media.contentId];
if(!item) {
// Content could not be found in repository
castDebugLogger.error(LOG_TAG, 'Content not found');
reject();
} else {
// Adjusting request to make requested content playable
request.media.contentUrl = item.stream.dash;
request.media.contentType = 'application/dash+xml';
castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);
// Add metadata
let metadata = new cast.framework.messages.MovieMediaMetadata();
metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
metadata.title = item.title;
metadata.subtitle = item.author;
request.media.metadata = metadata;
// Resolve request
resolve(request);
}
});
});
});
Możesz kontrolować, które komunikaty pojawiają się na nakładce debugowania, ustawiając poziom logowania w loggerLevelByTags
dla każdego tagu niestandardowego. Na przykład włączenie tagu niestandardowego z poziomem rejestrowania cast.framework.LoggerLevel.DEBUG
spowoduje wyświetlenie wszystkich dodanych komunikatów z komunikatami o błędach, ostrzeżeniach, informacjach i dziennikach debugowania. Włączenie tagu niestandardowego z poziomem WARNING
spowoduje wyświetlanie tylko komunikatów o błędach i ostrzeżeń.
Konfiguracja loggerLevelByTags
jest opcjonalna. Jeśli tag niestandardowy nie jest skonfigurowany na poziomie rejestratora, na nakładce debugowania będą się wyświetlać wszystkie komunikaty dziennika.
Dodaj ten kod pod rejestratorem zdarzeń CORE
:
// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}
// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
[LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};
Nakładka debugowania
Rejestrator debugowania Cast udostępnia na odbiorniku nakładkę debugowania, która umożliwia wyświetlanie niestandardowych komunikatów dziennika na urządzeniu przesyłającym. Użyj przycisku showDebugLogs
, aby przełączać nakładkę debugowania, i przycisku clearDebugLogs
, aby wyczyścić komunikaty dziennika na nakładce.
Dodaj ten kod, aby wyświetlić podgląd nakładki debugowania na odbiorniku.
context.addEventListener(cast.framework.system.EventType.READY, () => {
if (!castDebugLogger.debugOverlayElement_) {
// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
castDebugLogger.setEnabled(true);
// Show debug overlay
castDebugLogger.showDebugLogs(true);
// Clear log messages on debug overlay
castDebugLogger.clearDebugLogs();
}
});
13. Gratulacje
Wiesz już, jak utworzyć niestandardową aplikację odbiornika internetowego za pomocą pakietu SDK Cast Web pickupr.
Więcej informacji znajdziesz w przewodniku dla programistów dotyczącym komponentu WebView.