Na tej stronie wyjaśniono, jak wdrożyć radio na poziomie sprzętu i oprogramowania.
- Elementy systemu ilustrują i opisują stos technologii radiowej.
- Warstwa abstrakcji sprzętu radiowego (HAL) zapewnia struktury danych i interfejsy dla producentów OEM w celu wdrożenia radia rozgłoszeniowego, takiego jak radio AM/FM i radio cyfrowe (DAB), na poziomie sprzętowym.
- Implementacja sterowania radiem opiera się na
MediaSession
iMediaBrowse
, które umożliwiają aplikacjom multimediów i asystentów głosowych sterowanie radiem. Oprócz treści podanych poniżej zobacz Tworzenie aplikacji multimedialnych dla samochodów .
Elementy systemu
Stos radiowy rozgłoszeniowy zawiera następujące komponenty.
Aplikacja referencyjna radia
Aby uzyskać szczegółowe informacje na temat implementacji sterowania radiowego, zobacz Implementacja sterowania radiowego .
Przykładowa aplikacja radiowa Java ( packages/apps/Car/Radio
) służy jako implementacja referencyjna. Po uruchomieniu usługa aplikacji żąda od Menedżera radia otwarcia tunera radiowego. Następnie aplikacja może wysyłać do tunera radiowego żądania, takie jak dostrojenie określonej stacji radiowej, częstotliwości lub wyszukanie następnej dostępnej stacji radiowej. Aplikacja otrzymuje aktualizacje od Menedżera radia i tunera radiowego w radiu, takie jak aktualne informacje o programach, listy programów radiowych, konfiguracje i parametry zdefiniowane przez dostawcę. Referencyjna aplikacja Radio obsługuje tylko radio AM i FM. Producenci OEM mogą modyfikować lub wymieniać aplikację Radio według potrzeb.
Menedżer Radia
Gdy aplikacja żąda od Radio Managera otwarcia tunera, Menedżer Radio ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) żąda od usługi Broadcast Radio Service otwarcia sesji tunera, a następnie zamyka sesję w Tuner radiowy ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
), który jest zwracany do aplikacji. Tuner radiowy definiuje interfejsy API (takie jak strojenie, krok i anulowanie), które można wywoływać z aplikacji radiowych i wysyłać żądania do usługi Broadcast Radio Service. Metody wywołania zwrotnego ( RadioTuner.Callback
) zdefiniowane w Radio Tuner wysyłają aktualizacje dotyczące audycji radiowych HAL, takie jak aktualne informacje o programach, listy programów i parametry zdefiniowane przez dostawcę, z usługi Broadcast Radio Service do aplikacji.
Usługa radiofonii i telewizji
Usługa Broadcast Radio ( frameworks/base/services/core/java/com/android/server/broadcastradio
) to usługa kliencka dla Broadcast Radio HAL. Usługa Broadcast Radio Service koordynuje wielu menedżerów radiowych za pomocą HAL Broadcast Radio. Usługa Broadcast Radio Service obsługuje język definicji interfejsu HAL (HIDL) i język definicji interfejsu Androida (AIDL) . Usługa radiofonii i telewizji łączy się z AIDL HAL, jeśli istnieje jakakolwiek usługa AIDL HAL; w przeciwnym razie usługa łączy się z HIDL HAL. Usługa transmisji radiowej tworzy moduł radiowy dla każdej dostępnej instancji HAL (takiej jak AM, FM i DAB).
Każdy menedżer radiowy może poprosić usługę rozgłoszeniową o utworzenie sesji tunera w odpowiednim module radiowym, w zależności od typu radia. Każda sesja tunera może wywoływać metody, takie jak strojenie, krok i anulowanie (zdefiniowane w interfejsach HAL), aby wykonywać operacje na odpowiedniej instancji HAL rozgłoszeniowego radia. Kiedy jedna sesja tunera odbierze wywołanie zwrotne z instancji HAL w sprawie aktualizacji HAL, takie jak informacje o bieżącym programie, lista programów, flagi konfiguracyjne i parametry dostawcy, wywołania zwrotne dotyczące aktualizacji są wysyłane do wszystkich tunerów radiowych połączonych z tym samym modułem radiowym.
Transmisja radiowa HAL
Aby dowiedzieć się więcej o interfejsach HIDL i AIDL radia rozgłoszeniowego oraz różnicach między nimi, zobacz Interfejs HAL radia rozgłoszeniowego .
Warstwa abstrakcji sprzętu radiowego rozgłoszeniowego
W poniższych sekcjach opisano sposób pracy z warstwą abstrakcji sprzętu (HAL) w celu zaimplementowania radia rozgłoszeniowego.
Interfejs radiowy HAL
Radio rozgłoszeniowe HAL zapewnia struktury danych i interfejsy na poziomie sprzętowym do realizacji radia rozgłoszeniowego, takiego jak radio AM/FM i DAB.
Interfejsy HIDL 2.0 i AIDL
Radio rozgłoszeniowe HAL wykorzystuje interfejsy opisane w kolejnych rozdziałach.
Słuchacz zapowiedzi
IAnnouncementListener
to interfejs wywołania zwrotnego dla słuchacza zapowiedzi, który można zarejestrować w radiu HAL w celu odbioru ogłoszeń. Interfejs posiada następujące metody:
IOgłoszenieSłuchacz | ||
---|---|---|
Opis: Wywoływany za każdym razem, gdy zmieniała się lista ogłoszeń. | ||
HIDL 2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
AIDL | oneway void onListUpdated(in Announcement[] announcements) |
Zamknij uchwyt
ICloseHandle
to ogólny uchwyt zamykający służący do usuwania wywołania zwrotnego, które nie wymaga aktywnego interfejsu.
IZamknij uchwyt | ||
---|---|---|
Opis: Zamknij uchwyt. | ||
HIDL 2.0 | close() | |
AIDL | void close() |
Interfejs wywołania zwrotnego
ITunerCallback
to interfejs wywołania zwrotnego wywoływany przez radio rozgłoszeniowe HAL w celu wysyłania aktualizacji do usługi klienta HAL.
Oddzwonienie ITuner | ||
---|---|---|
Opis: wywoływane przez warstwę HAL, gdy operacja dostrajania (dostrajanie, wyszukiwanie (w formacie AIDL) lub skanowanie (w języku HIDL) i wykonanie kroku) kończy się asynchronicznym niepowodzeniem. | ||
HIDL 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Opis: Wywoływany, gdy dostrajanie, wyszukiwanie (w AIDL) lub skanowanie (w HIDL) lub wykonanie kroku się powiedzie. | ||
HIDL 2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
AIDL | void onTuneFailed(in Result result, in ProgramSelector selector) | |
Opis: Wywoływany, gdy dostrajanie, wyszukiwanie (w AIDL) lub skanowanie (w HIDL) lub wykonanie kroku się powiedzie. | ||
HIDL 2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Opis: Wywoływany, gdy lista programów jest aktualizowana; Rozmiar każdej porcji powinien być ograniczony do 500 kiB. | ||
HIDL 2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
AIDL | oneway onProgramListUpdated(ProgramListChunk chunk) | |
Opis: Wywoływany, gdy antena jest podłączona lub odłączona. | ||
HIDL 2.0 | oneway onAntennaStateChange(bool connected) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Opis: Wywoływany, gdy wartości parametrów specyficznych dla dostawcy są aktualizowane wewnętrznie w warstwie HAL (nie należy wywoływać po wywołaniu setParameters przez klienta HAL). | ||
HIDL 2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
AIDL | void onParametersUpdated(in VendorKeyValue[] parameters) | |
Opis: Nowość w AIDL. Wywoływana, gdy flaga konfiguracji jest aktualizowana wewnętrznie w warstwie HAL (nie powinna być wywoływana po wywołaniu setConfigFlag przez klienta HAL). | ||
HIDL 2.0 | Nie dotyczy. | |
AIDL | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
Podstawowy interfejs radiowy HAL
IBroadcastRadio
jest podstawowym interfejsem dla radia HAL. W HIDL 2.0 HAL użyj interfejsu ITunerSession
do tunera, aby wywołać operacje. Jednak w danym momencie aktywny jest maksymalnie jeden tuner (pod warunkiem, że każda instancja HAL radia ma tylko jeden chip tunera). ITunerSession
został usunięty z interfejsów AIDL, a jego interfejsy przeniesiono do IBroadcastRadio
.
IBroadcastRadio | ||
---|---|---|
Opis: Uzyskaj opis modułu i jego możliwości. | ||
HIDL 2.0 | getProperties() generates (Properties properties) | |
AIDL | Properties getProperties() | |
Opis: Pobiera bieżącą lub możliwą konfigurację regionu AM/FM. | ||
HIDL 2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
AIDL | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
Opis: Pobiera bieżącą konfigurację regionu DAB. | ||
HIDL 2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
AIDL | DabTableEntry[] getDabRegionConfig() | |
Opis: Pobiera obraz z pamięci podręcznej modułu radiowego. W AIDL rozmiar obrazu musi być mniejszy niż 1 MB ze względu na sztywne ograniczenie bufora transakcji segregatora. | ||
HIDL 2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
AIDL | byte[] getImage(in int id) | |
Opis: Rejestruje słuchacza zapowiedzi. | ||
HIDL 2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
AIDL | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
Opis:
| ||
HIDL 2.0 | openSession(ITunerCallback callback) generuje (Result result, ITunerSession session) | |
AIDL | void setTunerCallback(in ITunerCallback callback) | |
Opis:
| ||
HIDL 2.0 | close() | |
AIDL | unsetTunerCallback() | |
Opis: Dostraja się do określonego programu. | ||
HIDL 2.0 | tune(ProgramSelector program) generates (Result result) | |
AIDL | void tune(in ProgramSelector program) | |
Opis: Poszukuje następnego ważnego programu na antenie . Aby uniknąć nieporozumień w AIDL, scan została zmieniona na seek . | ||
HIDL 2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
AIDL | void seek(in boolean directionUp, in boolean skipSubChannel) | |
Opis: Kroki do sąsiedniego kanału, który nie może być zajęty przez żaden program. | ||
HIDL 2.0 | step(bool directionUp) generates (Result result) | |
AIDL | void step(in boolean directionUp) | |
Opis: Anuluje oczekujące operacje dostrajania, skanowania (w formacie HIDL), wyszukiwania (w formacie AIDL) lub operacji krokowych. | ||
HIDL 2.0 | cancel() | |
AIDL | void cancel() | |
Opis: Stosuje filtr do listy programów i rozpoczyna wysyłanie aktualizacji listy programów poprzez wywołanie zwrotne onProgramListUpdated . | ||
HIDL 2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
AIDL | void startProgramListUpdates(in ProgramFilter filter) | |
Opis: Zatrzymuje wysyłanie aktualizacji listy programów. | ||
HIDL 2.0 | stopProgramListUpdates() | |
AIDL | void stopProgramListUpdates() | |
Opis: Pobiera bieżące ustawienie danej flagi konfiguracyjnej. | ||
HIDL 2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
AIDL | boolean isConfigFlagSet(in ConfigFlag flag) | |
Opis: Ustawia daną flagę konfiguracyjną. | ||
HIDL 2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
AIDL | void setConfigFlag(in ConfigFlag flag, boolean value) | |
Opis: Ustawia wartości parametrów specyficzne dla dostawcy. | ||
HIDL 2.0 | setParameters(vec<VendorKeyValue> parameters) generuje , (vec<VendorKeyValue> results) | |
AIDL | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
Opis: pobiera wartości parametrów specyficzne dla dostawcy. | ||
HIDL 2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
AIDL | VendorKeyValue[] getParameters(in String[] keys) |
Wyjaśnienia interfejsu
Zachowanie asynchroniczne
Ponieważ każda operacja dostrajania (na przykład strojenie, skanowanie (w HIDL) lub wyszukiwanie (w AIDL) i krok) może być czasochłonne, a wątek nie powinien być blokowany przez długi czas, operacja powinna zaplanować czasochłonne operacje wystąpić później i szybko zwrócić status lub wynik. Szczegółowo każda operacja powinna:
- Anuluj wszystkie oczekujące operacje strojenia.
- Sprawdź, czy operacja może zostać przetworzona na podstawie danych wejściowych metody i stanu tunera.
- Zaplanuj zadanie dostrajania, a następnie natychmiast zwróć
Result
(w formacie HIDL) lubstatus
(w formacie AIDL). JeśliResult
lubstatus
toOK
, wywołanie zwrotne tuneratuneFailed
lubcurrentProgramInfoChanged
musi zostać wywołane, gdy zadanie strojenia nie powiodło się (na przykład z powodu przekroczenia limitu czasu) lub zostało zakończone.
Podobnie startProgramListUpdates
planuje również czasochłonne zadanie aktualizacji listy programów, które ma nastąpić później i szybko zwrócić status lub wynik. Metoda najpierw anuluje oczekujące żądania aktualizacji, a następnie planuje zadanie aktualizacji i szybko zwraca wynik.
Warunki wyścigu
Ze względu na asynchroniczne zachowanie operacji dostrajania (na przykład strojenie, skanowanie (w formacie HIDL) lub wyszukiwanie (w formacie AIDL) i krok) istnieje sytuacja wyścigu między anulowaniem operacji a operacjami dostrajania. Jeśli cancel
zostanie wywołane po zakończeniu operacji dostrajania warstwy HAL i przed zakończeniem wywołania zwrotnego, anulowanie można zignorować, a wywołanie zwrotne powinno zostać zakończone i odebrane przez klienta HAL.
Podobnie, jeśli stopProgramListUpdates
zostanie wywołane po zakończeniu aktualizacji listy programów przez warstwę HAL i przed zakończeniem wywołania zwrotnego onCurrentProgramInfoChanged
, stopProgramListUpdates
można zignorować i wywołanie zwrotne powinno zostać zakończone.
Limit rozmiaru danych
Ponieważ istnieje sztywny limit bufora transakcji spoiwa, limit danych dla niektórych metod interfejsu przekazujących dane o potencjalnie dużym rozmiarze jest wyjaśniony w AIDL HAL.
-
getImage
wymaga zwrócenia obrazu o rozmiarze mniejszym niż 1 MB. -
onProgramListUpdate
wymaga, aby każdychunk
był mniejszy niż 500 kiB. Większe listy programów muszą zostać podzielone przez implementację HAL na wiele części i przesłane za pośrednictwem wielu wywołań zwrotnych.
Zmiany w strukturach danych AIDL HAL
Oprócz zmian w interfejsach, zmiany te zostały zastosowane w strukturach danych zdefiniowanych w radiu AIDL HAL, które wykorzystuje AIDL.
-
Constant
wyliczenie jest usuwane w AIDL i definiowane jako const int wIBroadcastRadio
. Tymczasem nazwaANTENNA_DISCONNECTED_TIMEOUT_MS
została zmieniona naANTENNA_STATE_CHANGE_TIMEOUT_MS
. Dodano nową stałą intTUNER_TIMEOUT_MS
. Wszystkie operacje dostrajania, wyszukiwania i wykonywania kroków muszą zostać zakończone w tym czasie. - Enum
RDS
iDeemphasis
są usuwane w AIDL i definiowane jako const int wAmFmRegionConfig
. Odpowiednio, zarównofmDeemphasis
jak ifmRds
wProgramInfo
są zadeklarowane jako int, bitowy wynik obliczeń odpowiednich flag. Tymczasem nazwyD50
iD75
zostały odpowiednio zmienione naDEEMPHASIS_D50
iDEEMPHASIS_D75
. - Enum
ProgramInfoFlags
są usuwane w AIDL i definiowane jako const int wProgramInfo
z dodanym przedrostkiemFLAG_
. OdpowiednioinfoFlags
wProgramInfo
jest zadeklarowany jako int, bitowy wynik obliczeń flag. NazwaTUNED
została również zmieniona naFLAG_TUNABLE
, aby lepiej opisać definicję stacji, do której można dostroić stację. - W
AmFmBandRange
scanSpacing
została zmieniona naseekSpacing
, ponieważscan
została zmieniona naseek
w AIDL. - Ponieważ koncepcja unii została wprowadzona w AIDL,
MetadataKey
iMetadata
zdefiniowane w HIDL HAL nie są już używane.Metadata
unii AIDL są zdefiniowane w AIDL HAL. Każda wartość wyliczeniowa znajdująca się wcześniej wMetadataKey
jest teraz polem wMetadata
o typie string lub int, w zależności od ich definicji.
Implementacja sterowania radiowego
Implementacja sterowania radiem opiera się na MediaSession
i MediaBrowse
, które umożliwiają aplikacjom multimediów i asystentów głosowych sterowanie radiem. Aby uzyskać więcej informacji, zobacz Tworzenie aplikacji multimedialnych dla samochodów w witrynie developer.android.com.
Implementacja drzewa przeglądania multimediów jest dostępna w bibliotece car-broadcastradio-support w packages/apps/Car/libs
. Ta biblioteka zawiera również rozszerzenia ProgramSelector umożliwiające konwersję do i z URI. Zaleca się, aby implementacje radiowe korzystały z tej biblioteki do budowania powiązanego drzewa przeglądania.
Przełącznik źródła multimediów
Aby zapewnić płynne przejście między radiem a innymi aplikacjami wyświetlanymi w mediach, biblioteka car-media-common zawiera klasy, które należy zintegrować z aplikacją radia. MediaAppSelectorWidget
można uwzględnić w pliku XML aplikacji radiowej (ikona i menu rozwijane używane w referencyjnych aplikacjach multimedialnych i radiowych):
<com.android.car.media.common.MediaAppSelectorWidget android:id="@+id/app_switch_container" android:layout_width="@dimen/app_switch_widget_width" android:layout_height="wrap_content" android:background="@drawable/app_item_background" android:gravity="center" />
Ten widżet uruchamia element AppSelectionFragment
, który wyświetla listę źródeł multimediów, na które można się przełączyć. Jeśli wymagany jest interfejs użytkownika inny niż podany, możesz utworzyć niestandardowy widżet, aby uruchomić AppSelectionFragment
, gdy powinien zostać wyświetlony przełącznik.
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
Przykładowa implementacja jest dostępna w referencyjnej implementacji aplikacji radiowej, znajdującej się w packages/apps/Car/Radio
.
Szczegółowe specyfikacje sterowania
Interfejs MediaSession
(poprzez MediaSession.Callback
) udostępnia mechanizmy sterujące aktualnie odtwarzaną audycją radiową:
-
onPlay
,onStop
. (Nie)wyciszenie odtwarzania radia. -
onPause
. Pauza przesunięta w czasie (jeśli jest obsługiwana). -
onPlayFromMediaId
. Odtwarzaj dowolną zawartość z folderu najwyższego poziomu. Na przykład „Odtwórz FM” lub „Odtwórz radio”. -
onPlayFromUri
. Odtwórz określoną częstotliwość. Na przykład „Odtwórz 88,5 FM”. -
onSkipToNext
,onSkipToPrevious
. Dostrój następną lub poprzednią stację. -
onSetRating
. Dodaj lub usuń do lub z Ulubionych.
MediaBrowser udostępnia przestrajalny element MediaItem w trzech typach katalogów najwyższego poziomu:
- ( Opcjonalnie ) Programy (stacje). Ten tryb jest zwykle używany w radiotelefonach z dwoma tunerami do wskazywania wszystkich dostępnych dostrojonych stacji radiowych w lokalizacji użytkownika.
- Ulubione. Programy radiowe dodane do listy Ulubione, niektóre mogą być niedostępne (poza zasięgiem odbioru).
- Kanały pasma. Wszystkie fizycznie możliwe kanały w bieżącym regionie (87,9, 88,1, 88,3, 88,5, 88,7, 88,9, 89,1 itd.). Każdy zespół ma oddzielny katalog najwyższego poziomu.
Każdy element w każdym z tych folderów (AM/FM/Programy) jest elementem MediaItem z identyfikatorem URI, którego można używać z MediaSession do dostrajania. Każdy folder najwyższego poziomu (AM/FM/Programy) to element MediaItem z identyfikatorem mediaId, którego można używać z programem MediaSession w celu uruchomienia odtwarzania i zależy to od uznania producenta OEM. Na przykład „Play FM”, „Play AM” i „Play Radio” to niespecyficzne zapytania radiowe, które używają identyfikatora mediaId do wysyłania do aplikacji radiowej OEM. To aplikacja radiowa decyduje, co odtwarzać na podstawie ogólnego żądania i identyfikatora mediaId.
Sesja medialna
Ponieważ nie istnieje koncepcja wstrzymywania strumienia transmisji, akcje Odtwórz, Wstrzymaj i Zatrzymaj nie zawsze mają zastosowanie do radia. W przypadku radia akcja Stop jest powiązana z wyciszeniem strumienia, a Odtwórz z wyłączeniem wyciszenia.
Niektóre tunery radiowe (lub aplikacje) umożliwiają symulowanie pauzy w transmisji poprzez buforowanie zawartości i późniejsze jej odtwarzanie. W takich przypadkach użyj onPause
.
Odtwarzanie z akcji mediaId i URI ma na celu dostrojenie się do stacji pobranej z interfejsu MediaBrowser. MediaId to dowolny ciąg znaków dostarczany przez aplikację radia w celu narzucenia unikalnej (aby dany identyfikator wskazywał tylko jeden element) i stabilnej (a więc dany element miał ten sam identyfikator przez całą sesję) wartości umożliwiającej identyfikację danej stacji . Identyfikator URI będzie miał dobrze zdefiniowany schemat. Krótko mówiąc, forma ProgramSelector z URI. Chociaż zachowuje to atrybut wyjątkowości, nie musi być stabilny, chociaż może się zmienić, gdy stacja przejdzie na inną częstotliwość.
Z założenia onPlayFromSearch
nie jest używana. Obowiązkiem klienta (aplikacji towarzyszącej) jest wybranie wyniku wyszukiwania z drzewa MediaBrowser. Przeniesienie tej odpowiedzialności na aplikację radiową zwiększyłoby złożoność, wymagałoby formalnych umów dotyczących wyglądu zapytań łańcuchowych i skutkowałoby nierównym doświadczeniem użytkownika na różnych platformach sprzętowych.
Uwaga: aplikacja radiowa nie zawiera dodatkowych informacji, które byłyby przydatne do wyszukiwania nazwy stacji, która nie jest widoczna dla klienta za pośrednictwem interfejsu MediaBrowser.
Przejście do następnej lub poprzedniej stacji zależy od bieżącego kontekstu:
- Gdy aplikacja dostroi się do stacji z listy Ulubione, może przejść do następnej stacji z listy Ulubione.
- Słuchanie stacji z Listy Programów może skutkować dostrojeniem kolejnej dostępnej stacji, posortowanej według numeru kanału.
- Słuchanie dowolnego kanału może skutkować dostrojeniem się do następnego kanału fizycznego, nawet jeśli nie jest nadawany sygnał.
Aplikacja radiowa obsługuje te działania.
Obsługa błędów
Akcje TransportControls
(Odtwórz, Zatrzymaj i Dalej) nie dostarczają informacji zwrotnej na temat tego, czy akcja zakończyła się pomyślnie, czy nie. Jedynym sposobem wskazania błędu jest ustawienie stanu MediaSession na STATE_ERROR
z komunikatem o błędzie.
Aplikacja radiowa musi obsłużyć te działania i albo je wykonać, albo ustawić stan błędu. Jeżeli wykonanie polecenia Play nie jest natychmiastowe, w trakcie wykonywania polecenia należy zmienić stan odtwarzania na STATE_CONNECTING
(w przypadku bezpośredniego dostrojenia) lub STATE_SKIPPING_TO_PREVIOUS
lub NEXT
.
Klient powinien obserwować PlaybackState
i sprawdzić, czy sesja zmieniła bieżący program na żądany lub wprowadziła stan błędu. STATE_CONNECTING
nie może przekraczać 30 sekund. Jednakże bezpośrednie dostrojenie do danej częstotliwości AM/FM powinno działać znacznie szybciej.
Dodawaj i usuwaj ulubione
MediaSession obsługuje oceny, których można używać do kontrolowania Ulubionych. onSetRating
wywołany z oceną typu RATING_HEART
dodaje lub usuwa aktualnie dostrojoną stację do lub z listy Ulubione.
W przeciwieństwie do starszych ustawień wstępnych, model ten zakłada nieuporządkowaną i nieograniczoną listę ulubionych, gdzie każdy zapisany ulubiony jest przypisany do przedziału numerycznego (zwykle od 1 do 6). W rezultacie systemy oparte na ustawieniach wstępnych byłyby niekompatybilne z operacją onSetRating
.
Ograniczeniem interfejsu API MediaSession jest to, że można dodać lub usunąć tylko aktualnie dostrojoną stację. Na przykład elementy muszą zostać najpierw wybrane, zanim będzie można je usunąć. Jest to jedynie ograniczenie klienta MediaBrowser, np. aplikacji towarzyszącej. Aplikacja radiowa nie podlega podobnym ograniczeniom. Ta część jest opcjonalna, jeśli aplikacja nie obsługuje Ulubionych.
Przeglądarka multimediów
Aby wyrazić, które częstotliwości lub nazwy kanałów fizycznych (gdy dostrojenie dowolnego kanału jest odpowiednie dla danej technologii radiowej) obowiązują w danym regionie, dla każdego pasma wyszczególnione są wszystkie obowiązujące kanały (częstotliwości). W regionie USA oznacza to 101 kanałów FM z zakresu od 87,8 do 108,0 MHz (przy odstępie 0,2 MHz) i 117 kanałów AM w zakresie od 530 do 1700 kHz (przy odstępie 10 kHz). Ponieważ radio HD wykorzystuje tę samą przestrzeń kanałową, nie jest prezentowane osobno.
Lista aktualnie dostępnych programów radiowych jest płaska, ponieważ nie pozwala na stosowanie takich schematów wyświetlania, jak grupowanie według zespołu bezpośredniej transmisji audio (DAB).
Wpisy na liście ulubionych mogą nie podlegać strojeniu. Na przykład, jeśli dany program jest poza zakresem. Aplikacja radiowa może, ale nie musi, wykryć, czy wpis można wcześniej dostroić. Jeśli tak, może nie oznaczać wpisu jako nadającego się do odtworzenia.
Do identyfikacji folderów najwyższego poziomu stosowany jest ten sam mechanizm, który wykorzystuje Bluetooth. Oznacza to, że pakiet Extras obiektu MediaDescription
zawiera pole specyficzne dla tunera, tak jak robi to Bluetooth z EXTRA_BT_FOLDER_TYPE
. W przypadku radia rozgłoszeniowego prowadzi to do zdefiniowania w publicznym API następujących nowych pól:
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
. Jedna z następujących wartości:-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
. Aktualnie dostępne programy. -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
. Ulubione. -
BCRADIO_FOLDER_TYPE_BAND = 3
. Wszystkie kanały fizyczne dla danego pasma.
Nie ma potrzeby definiowania żadnych niestandardowych pól metadanych specyficznych dla radia, ponieważ wszystkie istotne dane pasują do istniejącego schematu
MediaBrowser.MediaItem
:- Nazwa programu (RDS PS, nazwa usługi DAB).
MediaDescription.getTitle
. - Częstotliwość FM. URI (patrz ProgramSelector ) lub
MediaDescription.getTitle
(jeśli wpis znajduje się w folderzeBROADCASTRADIO_FOLDER_TYPE_BAND
). - Identyfikatory specyficzne dla radia (RDS PI, DAB SId).
MediaDescription.getMediaUri
przeanalizowano do ProgramSelector.
Zwykle nie ma potrzeby pobierania częstotliwości FM dla wpisu w bieżącym programie lub liście Ulubione (ponieważ klient powinien operować na identyfikatorach mediów). Jeśli jednak zaistnieje taka potrzeba (na przykład do celów wyświetlania), jest ona obecna w identyfikatorze URI i można ją przeanalizować do
ProgramSelector
. To powiedziawszy, nie zaleca się używania identyfikatora URI do wybierania elementów w bieżącej sesji. Aby uzyskać szczegółowe informacje, zobaczProgramSelector
.Aby uniknąć problemów z wydajnością lub segregatorem, usługa MediaBrowser musi obsługiwać paginację:
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- Dodatkowe parametry funkcji
subscribe()
Uwaga: Domyślnie paginacja jest domyślnie zaimplementowana w wariancie
onLoadChildren()
bez obsługi opcji.Powiązane wpisy ze wszystkich typów list (surowe kanały, znalezione programy i ulubione) mogą mieć różne mediaId (zależy to od aplikacji radia; biblioteka wsparcia będzie miała je inne). Identyfikatory URI (w formie ProgramSelector) różnią się między nieprzetworzonymi kanałami i programami znalezionymi w większości przypadków (z wyjątkiem FM bez RDS), ale w większości są takie same między znalezionymi programami i ulubionymi (z wyjątkiem na przykład aktualizacji AF).
Posiadanie różnych mediaId dla wpisów z różnych typów list umożliwia podejmowanie na nich różnych działań. Możesz przeglądać listę Ulubione lub listę Wszystkie programy w
onSkipToNext
, w zależności od folderu ostatnio wybranegoMediaItem
(zobacz MediaSession ).Specjalne działania dostrojone
Lista programów umożliwia użytkownikom dostrojenie się do określonej stacji, ale nie pozwala użytkownikom na wprowadzanie ogólnych poleceń, takich jak „Dostrój do FM”, które mogłyby skutkować dostrojeniem do ostatnio słuchanej stacji w paśmie FM.
Aby wspierać takie akcje, niektóre katalogi najwyższego poziomu mają ustawioną flagę
FLAG_PLAYABLE
(wraz zFLAG_BROWSABLE
dla folderów).Działanie Dopasowuje się do Jak wydać Włącz radio Dowolny kanał radiowy startService(ACTION_PLAY_BROADCASTRADIO)
Lub
playFromMediaId(MediaBrowser. getRoot() )
Odtwórz FM Dowolny kanał FM Odtwórz z mediaId
pasma FM.Wybór programu do dostrojenia zależy od aplikacji. Jest to zazwyczaj ostatnio dostrojony kanał z podanej listy. Aby uzyskać szczegółowe informacje na temat
ACTION_PLAY_BROADCASTRADIO
, zobacz Ogólne zamiary gry .Wykrywanie i połączenie serwisowe
PackageManager
może bezpośrednio znaleźć drzewo radiowe transmisji MediaBrowserService obsługującej. Aby to zrobić, wywołajresolveService
z intencjąACTION_PLAY_BROADCASTRADIO
(zobacz Ogólne intencje gry ) i flagąMATCH_SYSTEM_ONLY
. Aby znaleźć wszystkie usługi obsługujące radio (może być ich więcej niż jedna, na przykład oddzielne AM/FM i satelita), użyjqueryIntentServices
.Rozwiązana usługa obsługuje również intencję powiązania
android.media.browse.MediaBrowserService
. Jest to weryfikowane w GTS.Aby połączyć się z wybraną usługą MediaBrowserService utwórz instancję
MediaBrowser
dla danego komponentu usługi iconnect
. Po nawiązaniu połączenia uchwyt do MediaSession można uzyskać poprzezgetSessionToken
.Aplikacja Radio może ograniczać pakiety klienckie, które mogą łączyć się w ramach implementacji usługi
onGetRoot
. Aplikacja powinna umożliwiać aplikacjom systemowym łączenie się bez umieszczania na białej liście. Szczegółowe informacje na temat umieszczania na białej liście znajdziesz w artykule Akceptowanie pakietu aplikacji Asystent i podpisu .Jeśli aplikacja specyficzna dla źródła (na przykład aplikacja radiowa) jest zainstalowana na urządzeniu bez obsługi takiego źródła, nadal reklamuje się jako obsługująca intencję
ACTION_PLAY_BROADCASTRADIO
, ale jej drzewo MediaBrowser nie będzie zawierać znaczników specyficznych dla radia. Zatem klient chcący sprawdzić czy dane źródło jest dostępne na urządzeniu musi:- Odkryj usługę radiową (zadzwoń do
resolveService
w celu uzyskaniaACTION_PLAY_BROADCASTRADIO
). - Utwórz
MediaBrowser
, a następnie połącz się z nim. - Określ obecność
MediaItem
za pomocą dodatkuEXTRA_BCRADIO_FOLDER_TYPE
.
Uwaga: W większości przypadków klient musi przeskanować wszystkie dostępne drzewa MediaBrowser, aby wykryć wszystkie dostępne źródła dla danego urządzenia.
Nazwy zespołów
Lista pasm jest reprezentowana przez zestaw katalogów najwyższego poziomu ze znacznikiem typu folderu ustawionym na
BCRADIO_FOLDER_TYPE_BAND
. Ich tytułyMediaItem
to zlokalizowane ciągi znaków reprezentujące nazwy zespołów. W większości przypadków będzie to to samo, co tłumaczenie na język angielski, ale klient nie może polegać na tym założeniu.Aby zapewnić stabilny mechanizm wyszukiwania określonych pasm, dodano dodatkowy znacznik dla folderów zespołów,
EXTRA_BCRADIO_BAND_NAME_EN
. Jest to niezlokalizowana nazwa pasma i może przyjmować tylko jedną z następujących predefiniowanych wartości:-
AM
-
FM
-
DAB
Jeśli zespołu nie ma na tej liście, nie należy ustawiać plakietki z nazwą zespołu. Jeśli jednak zespół znajduje się na liście, musi mieć ustawiony tag. Radio HD nie wymienia oddzielnych pasm, ponieważ wykorzystuje to samo podstawowe medium co AM/FM.
Ogólne zamiary gry
Każda aplikacja dedykowana do odtwarzania danego źródła (takiego jak radio lub płyta CD) musi obsługiwać ogólny zamiar odtwarzania , aby rozpocząć odtwarzanie niektórych treści ewentualnie ze stanu nieaktywnego (na przykład po uruchomieniu). Wybór treści do odtwarzania zależy od aplikacji, ale zazwyczaj jest to ostatnio odtwarzany program radiowy lub utwór z płyty CD. Dla każdego źródła dźwięku zdefiniowano odrębną intencję:
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA lub CD-Text -
android.car.intent.action.PLAY_DATADISC
: Optyczny dysk z danymi, taki jak CD/DVD, ale nie CD-DA (może to być CD w trybie mieszanym) -
android.car.intent.action.PLAY_AUX
: Bez określania, który port AUX -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: Bez określenia, które urządzenie USB -
android.car.intent.action.PLAY_LOCAL
: Lokalna pamięć multimediów (wbudowana pamięć flash)
Intencje zostały wybrane do wykorzystania w ogólnym poleceniu odtwarzania, ponieważ rozwiązują jednocześnie dwa problemy: samo ogólne polecenie odtwarzania i wykrywanie usług. Dodatkową korzyścią z posiadania takiego zamiaru byłaby możliwość wykonania tak prostej akcji bez otwierania sesji MediaBrowser.
Wykrywanie usług jest w rzeczywistości ważniejszym problemem rozwiązanym za pomocą tych zamiarów. Procedura wykrywania usług jest w ten sposób łatwa i jednoznaczna (patrz Wykrywanie i podłączanie usług ).
Aby ułatwić implementację niektórych klientów, istnieje alternatywny sposób wydania takiego polecenia Play (które również musi zostać zaimplementowane przez aplikację radiową): wydanie
playFromMediaId
z rootId węzła głównego (używanego jako mediaId). Chociaż węzeł główny nie jest przeznaczony do odtwarzania, jego rootId jest dowolnym ciągiem znaków, który można wykorzystać jako mediaId. Jednak klienci nie są zobowiązani do zrozumienia tego niuansu.Selektor programu
Chociaż
mediaId
wystarczy, aby wybrać kanał zMediaBrowserService
, zostaje on powiązany z sesją i nie jest spójny między dostawcami. W niektórych przypadkach klient może potrzebować wskaźnika bezwzględnego (takiego jak częstotliwość bezwzględna), aby utrzymać go między sesjami i urządzeniami.W dobie cyfrowych audycji radiowych sama częstotliwość nie wystarczy, aby dostroić się do konkretnej stacji. Dlatego użyj
ProgramSelector
, aby dostroić się do kanału analogowego lub cyfrowego.ProgramSelector
składa się z dwóch części:- Podstawowy identyfikator. Unikalny i stabilny identyfikator danej stacji radiowej, który nie zmienia się, ale może nie wystarczyć do dostrojenia się do tej stacji. Na przykład kod RDS PI, który w USA można przetłumaczyć na znak wywoławczy.
- Identyfikatory wtórne. Dodatkowe identyfikatory przydatne do dostrojenia się do tej stacji (na przykład częstotliwość), ewentualnie obejmujące identyfikatory z innych technologii radiowych. Na przykład stacja DAB może mieć rezerwowe nadawanie analogowe.
Aby umożliwić dopasowanie
ProgramSelector
do rozwiązania opartego naMediaBrowser
lubMediaSession
, zdefiniuj schemat URI w celu jego serializacji. Schemat jest zdefiniowany w następujący sposób:broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
W tym przykładzie część dotycząca dodatkowych identyfikatorów (po znaku zapytania (
?
)) jest opcjonalna i można ją usunąć, aby zapewnić stabilny identyfikator do użycia jakomediaId
. Na przykład:-
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=88500&AMFM_FREQUENCY=103300
-
broadcastradio://program/AMFM_FREQUENCY/102100
-
broadcastradio://program/DAB_SID_EXT/14895264?RDS_PI=1234
Część organizacyjna
program
(znana również jako gospodarz) zapewnia pewne miejsce na rozszerzenie programu w przyszłości. Ciągi typu identyfikatora są precyzyjnie określone jako ich nazwy w definicjiIdentifierType
HAL 2.x, a format wartości to liczba dziesiętna lub szesnastkowa (z przedrostkiem0x
).Wszystkie identyfikatory specyficzne dla dostawcy są reprezentowane przez przedrostek
VENDOR_
. Na przykładVENDOR_0
dlaVENDOR_START
iVENDOR_1
dlaVENDOR_START
plus 1. Takie identyfikatory URI są specyficzne dla sprzętu radiowego, na którym zostały wygenerowane i nie można ich przenosić między urządzeniami wyprodukowanymi przez różnych producentów OEM.Te identyfikatory URI muszą być przypisane do każdego elementu MediaItem w folderach radiowych najwyższego poziomu. Ponadto MediaSession musi obsługiwać zarówno
playFromMediaId
, jak iplayFromUri
. Jednak identyfikator URI jest przeznaczony przede wszystkim do ekstrakcji metadanych radiowych (takich jak częstotliwość FM) i trwałego przechowywania. Nie ma gwarancji, że identyfikator URI będzie dostępny dla wszystkich elementów multimedialnych (na przykład, gdy podstawowy typ identyfikatora nie jest jeszcze obsługiwany przez platformę). Z drugiej strony identyfikator multimediów zawsze działa. Nie zaleca się , aby klienci używali identyfikatora URI do wybierania elementów z bieżącej sesji MediaBrowser. Zamiast tego użyjplayFromMediaId
. To powiedziawszy, nie jest to opcjonalne w przypadku aplikacji obsługującej, a brakujące identyfikatory URI są zarezerwowane dla dobrze uzasadnionych przypadków.W pierwotnym projekcie zastosowano pojedynczy dwukropek zamiast sekwencji
://
po części schematu. Jednak ten pierwszy nie jest obsługiwany przezandroid.net.Uri
w przypadku bezwzględnych hierarchicznych odwołań do identyfikatora URI.Inne typy źródeł
Inne źródła dźwięku można obsługiwać w podobny sposób. Na przykład wejście pomocnicze i odtwarzacz Audio CD.
Pojedyncza aplikacja może obsługiwać wiele typów źródeł. W takich przypadkach zaleca się utworzenie osobnej usługi MediaBrowserService dla każdego typu źródła. Nawet w konfiguracji z wieloma obsługiwanymi źródłami/usługami MediaBrowserService zdecydowanie zaleca się posiadanie jednej sesji MediaSession w jednej aplikacji.
Płyta audio CD
Podobnie jak w przypadku Audio CD, aplikacja obsługująca takie dyski udostępniałaby MediaBrowser z jednym wpisem do przeglądania (lub większą liczbą, jeśli system ma zmieniarkę CD), który z kolei zawierałby wszystkie ścieżki z danej płyty CD. Jeśli system nie ma wiedzy o utworach na każdej płycie CD (np. gdy wszystkie dyski są włożone do kasety na raz i nie czyta ich wszystkich), to MediaItem dla całego dysku będzie po prostu
PLAYABLE
, a nieBROWSABLE
iPLAYABLE
. Jeśli w danym slocie nie ma dysku, przedmiot nie będziePLAYABLE
aniBROWSABLE
(ale każde miejsce musi zawsze znajdować się w drzewie).Wpisy te byłyby oznaczone w podobny sposób, jak foldery audycji radiowych; zawierałyby dodatkowe dodatkowe pola zdefiniowane w API MediaDescription:
-
EXTRA_CD_TRACK
: Dla każdegoMediaItem
na płycie audio CD, numer ścieżki oparty na 1. -
EXTRA_CD_DISK
: numer dysku oparty na 1.
W przypadku systemu obsługującego CD-Text i kompatybilnego dysku, element MediaItem najwyższego poziomu będzie miał tytuł dysku. Podobnie element MediaItems dla utworów będzie miał tytuł utworu.
Wejście pomocnicze
Aplikacja obsługująca wejście pomocnicze udostępnia drzewo MediaBrowser z jednym wpisem (lub większą liczbą, jeśli istnieje wiele portów) reprezentującym port wejścia AUX. Odpowiednia MediaSession pobiera swój mediaId i przełącza się na to źródło po otrzymaniu żądania
playFromMediaId
.Każdy wpis AUX MediaItem miałby dodatkowe pole
EXTRA_AUX_PORT_NAME
ustawione na niezlokalizowaną nazwę portu bez frazy „AUX”. Na przykład „AUX 1” zostałoby ustawione na „1”, „AUX front” na „front”, a „AUX” na pusty ciąg znaków. W lokalizacjach innych niż angielski znacznik nazwy pozostanie tym samym ciągiem znaków w języku angielskim. Mało prawdopodobne, jak dlaEXTRA_BCRADIO_BAND_NAME_EN
, wartości są zdefiniowane OEM i nie są ograniczone do predefiniowanej listy.Jeśli sprzęt może wykryć urządzenia podłączone do portu Aux, sprzęt powinien oznaczać MediaItem jako
PLAYABLE
, tylko wtedy, gdy wejście jest podłączone. Sprzęt powinien być nadal wyliczony (ale nie możnaPLAYABLE
), jeśli nic nie było podłączone do tego portu. Jeśli sprzęt nie ma takiej możliwości, MediaItem musi być zawsze ustawiony naPLAYABLE
.Dodatkowe pola
Zdefiniuj następujące pola:
-
EXTRA_CD_TRACK = "android.media.extra.CD_TRACK"
-
EXTRA_CD_DISK = "android.media.extra.CD_DISK"
-
EXTRA_AUX_PORT_NAME = "android.media.extra.AUX_PORT_NAME"
Klient musi przejrzeć MediaItems na najwyższym poziomie dla elementów posiadających zestaw
EXTRA_CD_DISK
lubEXTRA_AUX_PORT_NAME
.Szczegółowe przykłady
Poniższe przykłady odnoszą się do struktury drzewa MediaBrowser dla typów źródeł, które są częścią tego projektu.
Broadcast Radio MediaBrowserservice (obsługuje
ACTION_PLAY_BROADCASTRADIO
):- Stacje (przeglądanie)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (odtwarzane) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (grywalne) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (grywalne) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (grywalny) URI:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90,5 FM (grywalny) - FM bez RDSURI:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (grywalny) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC One (odtwarzane) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (odtwarzane) URI:
- Ulubione (przeglądane, playabalne)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (odtwarzane) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC dwa (nie grane) URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (odtwarzane) URI:
- AM (Browsable, Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (grywalny) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (grywalny) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (grywalny) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (grywalny) URI:
- FM (Browsable, Playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87,7 FM (grywalne) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87,9 FM (grywalne) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (grywalne) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87,7 FM (grywalne) URI:
- DAB (playabalne):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
Audio CD MediaBrowSerservice (obsługuje
ACTION_PLAY_AUDIOCD
):- Disc 1 (odtwarzany)
EXTRA_CD_DISK=1
- Disc 2 (przeglądalny, playabalny)
EXTRA_CD_DISK=2
- Ścieżka 1 (gra)
EXTRA_CD_TRACK=1
- Track 2 (odtwarzalny)
EXTRA_CD_TRACK=2
- Ścieżka 1 (gra)
- Moja muzyczna cd (przeglądacza, odtwarzana)
EXTRA_CD_DISK=3
- Wszystko przez siebie (grywalne)
EXTRA_CD_TRACK=1
- Reise, Reise (playable)
EXTRA_CD_TRACK=2
- Wszystko przez siebie (grywalne)
- Pusty gniazdo 4 (nie do gry)
EXTRA_CD_DISK=4
Aux MediaBrowsERService (obsługuje
ACTION_PLAY_AUX
):- Aux Front (playable)
EXTRA_AUX_PORT_NAME="front"
- Aux z tyłu (gra)
EXTRA_AUX_PORT_NAME="rear"
-