Auf dieser Seite wird erläutert, wie Funk auf Hardware- und Softwareebene implementiert wird.
- Systemkomponenten veranschaulicht und beschreibt den Funktechnologie-Stack.
- Broadcast Radio Hardware Abstraction Layer stellt Datenstrukturen und Schnittstellen für OEMs bereit, um Rundfunk wie AM/FM und DAB-Radio (Digital Audio Broadcasting) auf Hardwareebene zu implementieren.
- Die Implementierung der Radiosteuerung basiert auf
MediaSession
undMediaBrowse
, die es Medien- und Sprachassistenten-Apps ermöglichen, das Radio zu steuern. Zusätzlich zu den unten bereitgestellten Inhalten finden Sie weitere Informationen unter Erstellen von Medien-Apps für Autos .
Systemkomponenten
Der Rundfunkstapel umfasst die folgenden Komponenten.

Radio-Referenz-App
Einzelheiten zur Implementierung der Funksteuerung finden Sie unter Implementierung der Funksteuerung .
Als Referenzimplementierung dient eine Beispiel-Java-Radio-App ( packages/apps/Car/Radio
). Wenn der App-Dienst gestartet wird, fordert er Radio Manager auf, einen Radio-Tuner zu öffnen. Dann kann die App Anfragen an den Radiotuner senden, z. B. zum Einstellen eines bestimmten Radiosenders, einer bestimmten Frequenz oder zum Suchen des nächsten verfügbaren Radiosenders. Die App erhält Updates vom Radio Manager und Radio Tuner in Radio, wie z. B. aktuelle Programminformationen, Radioprogrammlisten, Konfigurationen und herstellerdefinierte Parameter. Die Referenz-Radio-App unterstützt nur AM- und FM-Radio. OEMs können die Radio-App nach Belieben modifizieren oder ersetzen.
Radiomanager
Wenn die App Radio Manager auffordert, einen Tuner zu öffnen, fordert der Radio Manager ( frameworks/base/core/java/android/hardware/radio/RadioManager.java
) den Broadcast Radio Service auf, eine Tuner-Sitzung zu öffnen, und umschließt die Sitzung dann in einer Radio Tuner ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java
), der an die App zurückgegeben wird. Der Radio-Tuner definiert APIs (wie Tune, Step und Cancel), die von Radio-Apps aufgerufen werden können und Anfragen an den Broadcast Radio Service senden. Rückrufmethoden ( RadioTuner.Callback
), die in Radio Tuner definiert sind, senden Aktualisierungen über die Rundfunk-HAL, wie z. B. aktuelle Programminformationen, Programmlisten und anbieterdefinierte Parameter, vom Rundfunkdienst an Apps.
Rundfunkdienst
Der Broadcast Radio Service ( frameworks/base/services/core/java/com/android/server/broadcastradio
) ist der Client-Service für Broadcast Radio HAL. Der Broadcast Radio Service koordiniert mehrere Radio Manager mit Broadcast Radio HALs. Der Broadcast Radio Service unterstützt Rundfunk-HALs der HAL-Schnittstellendefinitionssprache (HIDL) und der Android-Schnittstellendefinitionssprache (AIDL) . Der Rundfunkdienst verbindet sich mit dem AIDL HAL, wenn ein AIDL HAL-Dienst existiert; andernfalls wird der Dienst mit der HIDL HAL verknüpft. Der Broadcast Radio Service erstellt ein Radiomodul für jede verfügbare HAL-Instanz (z. B. AM, FM und DAB).
Jeder Radio Manager kann den Broadcast Radio Service auffordern, eine Tuner-Session auf dem entsprechenden Radiomodul basierend auf dem Radiotyp zu erstellen. Jede Tuner-Session kann Methoden aufrufen, wie z. B. tune, step und cancel (definiert in HAL-Schnittstellen), um Operationen an der entsprechenden Rundfunk-HAL-Instanz auszuführen. Wenn eine Tuner-Sitzung bei einem HAL-Update einen Rückruf von der HAL-Instanz erhält, wie z. B. aktuelle Programminformationen, Programmliste, Konfigurations-Flags und Herstellerparameter, werden Rückrufe über das Update an alle Radio-Tuner gesendet, die mit demselben Radiomodul verbunden sind.
Radiosender HAL
Um mehr über die HIDL- und AIDL-Schnittstellen des Rundfunks und die Unterschiede zwischen den beiden zu erfahren, siehe HAL-Schnittstelle des Rundfunks .
Rundfunk-Hardware-Abstraktionsschicht
In den folgenden Abschnitten wird beschrieben, wie Sie mit der Hardwareschicht arbeiten, um Rundfunk zu implementieren.
Rundfunk-HAL-Schnittstelle
Die Rundfunk-HAL stellt Datenstrukturen und Schnittstellen auf Hardwareebene bereit, um Rundfunk, wie etwa AM/FM- und DAB-Radio, zu implementieren.
HIDL 2.0- und AIDL-Schnittstellen
Das Rundfunkgerät HAL verwendet die in den folgenden Abschnitten beschriebenen Schnittstellen.
Ansage-Hörer
IAnnouncementListener
ist die Callback-Schnittstelle für den Ansage-Listener, der im Rundfunk-HAL registriert werden kann, um Ansagen zu empfangen. Die Schnittstelle hat die folgenden Methoden:
IAnnouncementListener | ||
---|---|---|
Beschreibung: Wird immer dann gerufen, wenn sich die Ansageliste geändert hat. | ||
HIDL2.0 | oneway onListUpdated(vec<Announcement> announcements) | |
AIDL | oneway void onListUpdated(in Announcement[] announcements) |
Griff schließen
ICloseHandle
ist das generische Close-Handle zum Entfernen eines Rückrufs, der keine aktive Schnittstelle benötigt.
ICloseHandle | ||
---|---|---|
Beschreibung: Schließen Sie den Griff. | ||
HIDL2.0 | close() | |
AIDL | void close() |
Callback-Schnittstelle
ITunerCallback
ist die Rückrufschnittstelle, die von der Rundfunk-HAL aufgerufen wird, um Aktualisierungen an den HAL-Clientdienst zu senden.
ITunerCallback | ||
---|---|---|
Beschreibung: Wird von der HAL aufgerufen, wenn ein Tuning-Vorgang (tune, seek (in AIDL) oder scan (in HIDL) und Step erfolgreich) asynchron fehlschlägt. | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Beschreibung: Wird aufgerufen, wenn tune, seek (in AIDL) oder scan (in HIDL) oder step erfolgreich sind. | ||
HIDL2.0 | oneway onTuneFailed(Result result, ProgramSelector selector) | |
AIDL | void onTuneFailed(in Result result, in ProgramSelector selector) | |
Beschreibung: Wird aufgerufen, wenn tune, seek (in AIDL) oder scan (in HIDL) oder step erfolgreich sind. | ||
HIDL2.0 | oneway onCurrentProgramInfoChanged(ProgramInfo info) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Beschreibung: Wird aufgerufen, wenn die Programmliste aktualisiert wird; Die Größe jedes Chunks sollte auf 500 KB begrenzt sein. | ||
HIDL2.0 | oneway onProgramListUpdated(ProgramListChunk chunk) | |
AIDL | oneway onProgramListUpdated(ProgramListChunk chunk) | |
Beschreibung: Wird aufgerufen, wenn die Antenne angeschlossen oder getrennt wird. | ||
HIDL2.0 | oneway onAntennaStateChange(bool connected) | |
AIDL | void onCurrentProgramInfoChanged(in ProgramInfo info) | |
Beschreibung: Wird aufgerufen, wenn die herstellerspezifischen Parameterwerte intern in HAL aktualisiert werden (sollte nicht nach dem Aufruf von setParameters durch den HAL-Client aufgerufen werden). | ||
HIDL2.0 | oneway onParametersUpdated(vec<VendorKeyValue> parameters) | |
AIDL | void onParametersUpdated(in VendorKeyValue[] parameters) | |
Beschreibung: Neu in AIDL. Wird aufgerufen, wenn das Konfigurations-Flag intern in der HAL aktualisiert wird (sollte nicht nach dem Aufruf von setConfigFlag durch den HAL-Client aufgerufen werden). | ||
HIDL2.0 | Unzutreffend. | |
AIDL | void onConfigFlagUpdated(in ConfigFlag flag, in boolean value) |
Primäre Rundfunk-HAL-Schnittstelle
IBroadcastRadio
ist die primäre Schnittstelle für den Rundfunksender HAL. Verwenden Sie in der HIDL 2.0 HAL die ITunerSession
Schnittstelle zum Tuner, um Vorgänge aufzurufen. Es ist jedoch höchstens ein Tuner gleichzeitig aktiv (vorausgesetzt, jede Rundfunk-HAL-Instanz hat nur einen Tuner-Chip). ITunerSession
wurde aus den AIDL-Schnittstellen entfernt und seine Schnittstellen zu IBroadcastRadio
.
IBroadcastRadio | ||
---|---|---|
Beschreibung: Rufen Sie die Beschreibung eines Moduls und seiner Fähigkeiten ab. | ||
HIDL2.0 | getProperties() generates (Properties properties) | |
AIDL | Properties getProperties() | |
Beschreibung: Ruft die aktuelle oder mögliche AM/FM-Regionskonfiguration ab. | ||
HIDL2.0 | getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config) | |
AIDL | AmFmRegionConfig getAmFmRegionConfig(bool full) | |
Beschreibung: Ruft die aktuelle Konfiguration der DAB-Region ab. | ||
HIDL2.0 | getDabRegionConfig() generates (Result result, vec<DabTableEntry> config) | |
AIDL | DabTableEntry[] getDabRegionConfig() | |
Beschreibung: Ruft ein Bild aus dem Funkmodul-Cache ab. In AIDL muss die Bildgröße aufgrund einer festen Begrenzung des Binder-Transaktionspuffers weniger als 1 MB betragen. | ||
HIDL2.0 | getImage(uint32_t id) generates (vec<uint8_t> image) | |
AIDL | byte[] getImage(in int id) | |
Beschreibung: Registriert den Ansage-Listener. | ||
HIDL2.0 | registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle) | |
AIDL | ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled) | |
Beschreibung:
| ||
HIDL2.0 | openSession(ITunerCallback callback) generiert (Result result, ITunerSession session) | |
AIDL | void setTunerCallback(in ITunerCallback callback) | |
Beschreibung:
| ||
HIDL2.0 | close() | |
AIDL | unsetTunerCallback() | |
Beschreibung: Stellt auf ein bestimmtes Programm ein. | ||
HIDL2.0 | tune(ProgramSelector program) generates (Result result) | |
AIDL | void tune(in ProgramSelector program) | |
Beschreibung: Sucht das nächste gültige Programm auf Sendung . Um Verwirrung in AIDL zu vermeiden, wird scan in seek umbenannt. | ||
HIDL2.0 | scan(bool directionUp, bool skipSubChannel) generates (Result result) | |
AIDL | void seek(in boolean directionUp, in boolean skipSubChannel) | |
Beschreibung: Sprung zum Nachbarkanal, der von keinem Programm belegt sein darf. | ||
HIDL2.0 | step(bool directionUp) generates (Result result) | |
AIDL | void step(in boolean directionUp) | |
Beschreibung: Bricht anstehende Tune-, Scan- (in HIDL) oder Seek- (in AIDL) oder Step-Operationen ab. | ||
HIDL2.0 | cancel() | |
AIDL | void cancel() | |
Beschreibung: Wendet einen Filter auf die Programmliste an und beginnt mit dem Senden von Programmlistenaktualisierungen über den onProgramListUpdated Callback. | ||
HIDL2.0 | startProgramListUpdates(ProgramFilter filter) generates (Result result) | |
AIDL | void startProgramListUpdates(in ProgramFilter filter) | |
Beschreibung: Stoppt das Senden von Aktualisierungen der Programmliste. | ||
HIDL2.0 | stopProgramListUpdates() | |
AIDL | void stopProgramListUpdates() | |
Beschreibung: Ruft die aktuelle Einstellung eines bestimmten Konfigurationsflags ab. | ||
HIDL2.0 | isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value) | |
AIDL | boolean isConfigFlagSet(in ConfigFlag flag) | |
Beschreibung: Setzt das angegebene Konfigurationsflag. | ||
HIDL2.0 | setConfigFlag(ConfigFlag flag, bool value) generates (Result result) | |
AIDL | void setConfigFlag(in ConfigFlag flag, boolean value) | |
Beschreibung: Legt herstellerspezifische Parameterwerte fest. | ||
HIDL2.0 | setParameters(vec<VendorKeyValue> parameters) erzeugt , (vec<VendorKeyValue> results) | |
AIDL | VendorKeyValue[] setParameters(in VendorKeyValue[] parameters) | |
Beschreibung: Ruft herstellerspezifische Parameterwerte ab. | ||
HIDL2.0 | getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters) | |
AIDL | VendorKeyValue[] getParameters(in String[] keys) |
Erläuterungen zur Schnittstelle
Asynchrones Verhalten
Da jeder Optimierungsvorgang (z. B. Tune, Scan (in HIDL) oder Seek (in AIDL) und Schritt) zeitaufwändig sein kann und der Thread nicht für längere Zeit blockiert werden sollte, sollte der Vorgang zeitaufwändige Vorgänge planen später auftreten und schnell einen Status oder ein Ergebnis zurückgeben. Im Einzelnen sollte jede Operation:
- Brechen Sie alle ausstehenden Tuning-Vorgänge ab.
- Überprüfen Sie, ob die Operation basierend auf den Methodeneingaben und dem Status des Tuners verarbeitet werden kann.
- Planen Sie die Optimierungsaufgabe und geben Sie dann sofort das
Result
(in HIDL) oder denstatus
(in AIDL) zurück. Wenn dasResult
oder derstatus
OK
ist, muss der Tuner-CallbacktuneFailed
odercurrentProgramInfoChanged
aufgerufen werden, wenn die Optimierungsaufgabe fehlgeschlagen ist (z. B. aufgrund einer Zeitüberschreitung) oder abgeschlossen ist.
In ähnlicher Weise startProgramListUpdates
auch die zeitaufwändige Aufgabe, die Programmliste zu aktualisieren, um sie später auszuführen und schnell einen Status oder ein Ergebnis zurückzugeben. Das Verfahren bricht zuerst anstehende Aktualisierungsanforderungen ab und plant dann die Aktualisierungsaufgabe und gibt das Ergebnis schnell zurück.
Rennbedingung
Aufgrund des asynchronen Verhaltens von Tuning-Operationen (z. B. tune, scan (in HIDL) oder seek (in AIDL) und step) besteht eine Wettlaufbedingung zwischen dem Abbrechen der Operation und den Tuning-Operationen. Wenn cancel
aufgerufen wird, nachdem die HAL einen Abstimmungsvorgang abgeschlossen hat und bevor der Rückruf abgeschlossen ist, kann der Abbruch ignoriert werden und der Rückruf sollte abgeschlossen und vom HAL-Client empfangen werden.
Wenn stopProgramListUpdates
aufgerufen wird, nachdem die HAL eine Programmlistenaktualisierung abgeschlossen hat und bevor der onCurrentProgramInfoChanged
Rückruf abgeschlossen ist, kann stopProgramListUpdates
ignoriert werden und der Rückruf sollte abgeschlossen werden.
Begrenzung der Datengröße
Da es eine feste Grenze für den Binder-Transaktionspuffer gibt, wird die Datengrenze für einige Schnittstellenmethoden, die Daten mit einer potenziell großen Größe übergeben, in der AIDL HAL geklärt.
-
getImage
erfordert, dass das zurückgegebene Bild weniger als 1 MB groß ist. -
onProgramListUpdate
erfordert, dass jederchunk
kleiner als 500 KB ist. Größere Programmlisten müssen von der HAL-Implementierung in mehrere Blöcke aufgeteilt und durch mehrere Rückrufe gesendet werden.
Änderungen in AIDL HAL-Datenstrukturen
Zusätzlich zu den Änderungen in den Schnittstellen wurden diese Änderungen auf die Datenstrukturen angewendet, die in der Rundfunk-AIDL HAL definiert sind, die die Vorteile der AIDL nutzt.
-
Constant
enum wird in AIDL entfernt und inIBroadcastRadio
als const int definiert. Inzwischen wirdANTENNA_DISCONNECTED_TIMEOUT_MS
inANTENNA_STATE_CHANGE_TIMEOUT_MS
umbenannt. Eine neue Konstante intTUNER_TIMEOUT_MS
wird hinzugefügt. Alle Abstimmungs-, Such- und Schrittoperationen müssen innerhalb dieser Zeit abgeschlossen sein. - Enum
RDS
und Deemphasis werden inDeemphasis
entfernt und inAmFmRegionConfig
als const int definiert. Dementsprechend werden sowohlfmDeemphasis
alsfmRds
inProgramInfo
als int deklariert, ein Bit-Berechnungsergebnis der jeweiligen Flags. In der Zwischenzeit werdenD50
undD75
inDEEMPHASIS_D50
bzw.DEEMPHASIS_D75
umbenannt. - Enum
ProgramInfoFlags
werden in AIDL entfernt und inProgramInfo
als const int mit einem hinzugefügten PräfixFLAG_
definiert. Entsprechend werdeninfoFlags
inProgramInfo
als int deklariert, ein Bit-Berechnungsergebnis von Flags.TUNED
wurde auch inFLAG_TUNABLE
umbenannt, um besser zu beschreiben, wie der Sender eingestellt werden kann. - In
AmFmBandRange
wirdscanSpacing
inseekSpacing
umbenannt, dascan
in AIDL inseek
umbenannt wurde. - Da das Union -Konzept in AIDL eingeführt wurde, werden
MetadataKey
undMetadata
, die in HIDL HAL definiert sind, nicht mehr verwendet. In AIDL HAL sind AIDL-Union-Metadata
definiert. Jeder Aufzählungswert, der zuvor inMetadataKey
enthalten war, ist jetzt ein Feld inMetadata
mit dem Typ string oder int, je nach Definition.
Implementierung der Funksteuerung
Die Implementierung der Radiosteuerung basiert auf MediaSession
und MediaBrowse
, die es Medien- und Sprachassistenten-Apps ermöglichen, das Radio zu steuern. Weitere Informationen finden Sie unter Erstellen von Medien-Apps für Autos auf developer.android.com.
Eine Medienbaum-Implementierung wird in der car-broadcastradio-support-Bibliothek in packages/apps/Car/libs
bereitgestellt. Diese Bibliothek enthält auch Erweiterungen von ProgramSelector zum Konvertieren in und aus URI. Es wird empfohlen, dass Funkimplementierungen diese Bibliothek verwenden, um den zugehörigen Suchbaum zu erstellen.
Umschalter für Medienquellen
Um einen nahtlosen Übergang zwischen Radio und anderen in Medien angezeigten Apps bereitzustellen, enthält die Car-Media-Common-Bibliothek Klassen, die in die Radio-App integriert werden sollten. MediaAppSelectorWidget
kann in das XML für die Radio-App aufgenommen werden (das Symbol und die Dropdown-Liste, die in den Referenzmedien und Radio-Apps verwendet werden):
<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" />
Dieses Widget startet das AppSelectionFragment
, das eine Liste von Medienquellen anzeigt, zu denen gewechselt werden kann. Wenn eine andere als die bereitgestellte Benutzeroberfläche gewünscht wird, können Sie ein benutzerdefiniertes Widget erstellen, um das AppSelectionFragment
zu starten, wenn der Umschalter angezeigt werden soll.
AppSelectionFragment newFragment = AppSelectionFragment.create(widget, packageName, fullScreen); newFragment.show(mActivity.getSupportFragmentManager(), null);
Eine Beispielimplementierung wird in der Referenz-Radio-App-Implementierung bereitgestellt, die sich in packages/apps/Car/Radio
befindet.
Detaillierte Steuerungsspezifikationen
Die Schnittstelle MediaSession
(über MediaSession.Callback
) bietet Kontrollmechanismen für das aktuell laufende Radioprogramm:
-
onPlay
,onStop
. Radiowiedergabe (auf)stumm schalten. -
onPause
. Zeitversetzte Pause (sofern unterstützt). -
onPlayFromMediaId
. Spielen Sie beliebige Inhalte aus einem Ordner der obersten Ebene ab. Beispiel: „FM abspielen“ oder „Radio abspielen“. -
onPlayFromUri
. Spielen Sie eine bestimmte Frequenz. Beispiel: „Spiele 88,5 FM“. -
onSkipToNext
,onSkipToPrevious
. Stellen Sie einen nächsten oder vorherigen Sender ein. -
onSetRating
. Hinzufügen oder Entfernen zu oder aus Favoriten.
Der MediaBrowser stellt ein einstellbares MediaItem über drei Arten von Verzeichnissen der obersten Ebene bereit:
- ( Optional ) Programme (Stationen). Dieser Modus wird typischerweise von Dual-Tuner-Funkgeräten verwendet, um alle verfügbaren abstimmbaren Radiosender am Standort des Benutzers anzuzeigen.
- Favoriten. Radioprogramme, die der Favoritenliste hinzugefügt wurden, sind möglicherweise nicht verfügbar (außerhalb des Empfangsbereichs).
- Bandkanäle. Alle physikalisch möglichen Kanäle in der aktuellen Region (87.9, 88.1, 88.3, 88.5, 88.7, 88.9, 89.1 usw.). Jede Band hat ein separates Top-Level-Verzeichnis.

Jedes Element in jedem dieser Ordner (AM/FM/Programs) ist ein MediaItem mit einer URI, die mit MediaSession zum Tunen verwendet werden kann. Jeder Ordner der obersten Ebene (AM/FM/Programme) ist ein MediaItem mit einer mediaId, die mit MediaSession zum Auslösen der Wiedergabe verwendet werden kann und im Ermessen des OEM liegt. Beispielsweise sind „FM abspielen“, „AM abspielen“ und „Radio abspielen“ alles unspezifische Radioabfragen, die eine mediaId zum Senden an die OEM-Radio-App verwenden. Es liegt an der Radio-App, anhand der generischen Anfrage und der mediaId zu bestimmen, was wiedergegeben werden soll.
Mediensitzung
Da es kein Konzept zum Anhalten eines Broadcast-Streams gibt, gelten die Aktionen Play, Pause und Stop nicht immer für Radio. Beim Radio ist die Stop-Aktion mit dem Stummschalten des Streams verbunden, während Play mit dem Aufheben der Stummschaltung verbunden ist.
Einige Radiotuner (oder Apps) bieten die Möglichkeit, eine Unterbrechung des Sendestroms zu simulieren, indem Inhalte zwischengespeichert und später wiedergegeben werden. Verwenden Sie in solchen Fällen onPause
.
Das Abspielen von mediaId- und URI-Aktionen dient dazu, einen Sender einzustellen, der von der MediaBrowser-Schnittstelle abgerufen wird. Die mediaId ist eine willkürliche Zeichenfolge, die von der Radio-App bereitgestellt wird, um einen eindeutigen (so dass eine bestimmte ID auf nur ein Element zeigt) und stabilen Wert (so dass ein bestimmtes Element während der gesamten Sitzung dieselbe ID hat) aufzuerlegen, mit dem ein bestimmter Sender identifiziert werden kann . Der URI hat ein wohldefiniertes Schema. Kurz gesagt, eine URI-isierte Form von ProgramSelector. Während dies das Eindeutigkeitsattribut bewahrt, muss es nicht stabil sein, obwohl es sich ändern kann, wenn sich die Station auf eine andere Frequenz bewegt.
onPlayFromSearch
wird standardmäßig nicht verwendet. Es liegt in der Verantwortung des Clients (Begleit-App), ein Suchergebnis aus der MediaBrowser-Struktur auszuwählen. Die Übertragung dieser Verantwortung auf die Radio-App würde die Komplexität erhöhen, formelle Verträge darüber erfordern, wie Zeichenfolgenabfragen angezeigt werden sollen, und zu einer uneinheitlichen Benutzererfahrung auf verschiedenen Hardwareplattformen führen.
Hinweis: Die Radio-App enthält keine zusätzlichen Informationen, die nützlich wären, um nach einem Sendernamen zu suchen, der dem Client nicht über die MediaBrowser-Schnittstelle angezeigt wird.
Das Springen zum nächsten oder vorherigen Sender hängt vom aktuellen Kontext ab:
- Wenn eine App auf einen Sender aus der Favoritenliste eingestellt ist, kann die App zum nächsten Sender aus der Favoritenliste wechseln.
- Das Hören eines Senders aus der Programmliste kann dazu führen, dass der nächste verfügbare Sender eingestellt wird, sortiert nach der Kanalnummer.
- Das Hören eines beliebigen Kanals kann dazu führen, dass auf den nächsten physikalischen Kanal umgeschaltet wird, selbst wenn kein Sendesignal vorhanden ist.
Die Radio-App verarbeitet diese Aktionen.
Fehlerbehandlung
TransportControls
Aktionen (Play, Stop und Next) geben kein Feedback darüber, ob die Aktion erfolgreich war oder nicht. Die einzige Möglichkeit, einen Fehler anzuzeigen, besteht darin, den MediaSession-Status mit einer Fehlermeldung auf STATE_ERROR
zu setzen.
Die Radio-App muss diese Aktionen verarbeiten und sie entweder ausführen oder einen Fehlerzustand festlegen. Wenn die Ausführung des Play-Befehls nicht sofort erfolgt, sollte der Wiedergabezustand auf STATE_CONNECTING
(bei direkter Abstimmung) oder STATE_SKIPPING_TO_PREVIOUS
oder NEXT
geändert werden, während der Befehl ausgeführt wird.
Der Client sollte den PlaybackState
überwachen und überprüfen, ob die Sitzung das aktuelle Programm in das angeforderte geändert oder in den Fehlerstatus versetzt hat. STATE_CONNECTING
darf 30 Sekunden nicht überschreiten. Eine direkte Abstimmung auf eine bestimmte AM/FM-Frequenz sollte jedoch viel schneller ablaufen.
Hinzufügen und Entfernen von Favoriten
MediaSession bietet Bewertungsunterstützung, die zur Steuerung von Favoriten verwendet werden kann. onSetRating
, das mit einer Bewertung vom Typ RATING_HEART
fügt den aktuell eingestellten Sender zu oder aus der Favoritenliste hinzu oder entfernt ihn.
Im Gegensatz zu älteren Voreinstellungen geht dieses Modell von einer ungeordneten und unbegrenzten Favoritenliste aus, wenn jeder gespeicherte Favorit einem numerischen Platz (typischerweise 1 bis 6) zugeordnet wurde. Infolgedessen wären voreingestellte Systeme mit onSetRating
-Betrieb inkompatibel.
Die Einschränkung der MediaSession-API besteht darin, dass nur der aktuell eingestellte Sender hinzugefügt oder entfernt werden kann. Beispielsweise müssen Elemente zuerst ausgewählt werden, bevor sie entfernt werden können. Dies ist nur eine Einschränkung des MediaBrowser-Clients, z. B. einer Begleit-App. Die Radio-App ist nicht ähnlich eingeschränkt. Dieser Teil ist optional, wenn eine App Favoriten nicht unterstützt.
MediaBrowser
Um auszudrücken, welche Frequenzen oder physikalischen Kanalnamen (wenn das Einstellen auf einen beliebigen Kanal für eine bestimmte Funktechnologie geeignet ist) für eine bestimmte Region gültig sind, werden alle gültigen Kanäle (Frequenzen) für jedes Band aufgelistet. In der US-Region beläuft sich dies auf 101 FM-Kanäle im Bereich von 87,8 bis 108,0 MHz (unter Verwendung eines Abstands von 0,2 MHz) und 117 AM-Kanäle im Bereich von 530 bis 1700 kHz (unter Verwendung eines Abstands von 10 kHz). Da HD-Radio denselben Kanalraum verwendet, wird es nicht separat dargestellt.
Die Liste der derzeit verfügbaren Radioprogramme ist dahingehend flach, dass dies keine Anzeigeschemata zulässt, wie beispielsweise eine Gruppierung nach DAB-Ensemble (Direct Audio Broadcast).
Einträge in der Favoritenliste sind möglicherweise nicht abstimmbar. Zum Beispiel, wenn ein bestimmtes Programm außerhalb des Bereichs liegt. Die Radio-App kann vorher erkennen, ob der Eintrag eingestellt werden kann oder nicht. Wenn dies der Fall ist, wird der Eintrag möglicherweise nicht als spielbar markiert.
Um Ordner der obersten Ebene zu identifizieren, wird derselbe Mechanismus angewendet, der von Bluetooth verwendet wird. Das heißt, ein Extras-Bundle des MediaDescription
-Objekts enthält ein tunerspezifisches Feld, genau wie Bluetooth es mit EXTRA_BT_FOLDER_TYPE
. Im Falle des Rundfunks führt dies zur Definition der folgenden neuen Felder in der öffentlichen API:
-
EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE"
. Einer der folgenden Werte:-
BCRADIO_FOLDER_TYPE_PROGRAMS = 1
. Aktuell verfügbare Programme. -
BCRADIO_FOLDER_TYPE_FAVORITES = 2
. Favoriten. -
BCRADIO_FOLDER_TYPE_BAND = 3
. Alle physischen Kanäle für ein bestimmtes Band.
Es ist nicht erforderlich, radiospezifische benutzerdefinierte Metadatenfelder zu definieren, da alle relevanten Daten in das vorhandene
MediaBrowser.MediaItem
Schema passen:- Programmname (RDS PS, DAB-Dienstname).
MediaDescription.getTitle
. - UKW-Frequenz. URI (siehe ProgramSelector ) oder
MediaDescription.getTitle
(wenn sich ein Eintrag im OrdnerBROADCASTRADIO_FOLDER_TYPE_BAND
befindet). - Radiospezifische Kennungen (RDS PI, DAB SId).
MediaDescription.getMediaUri
in ProgramSelector geparst.
Typischerweise besteht keine Notwendigkeit, die UKW-Frequenz für einen Eintrag im aktuellen Programm oder in der Favoritenliste abzurufen (da der Client mit Medien-IDs arbeiten sollte). Sollte jedoch ein solcher Bedarf entstehen (z. B. zu Anzeigezwecken), ist er in der URI vorhanden und kann in
ProgramSelector
geparst werden. Es wird jedoch nicht empfohlen, den URI zum Auswählen von Elementen in der aktuellen Sitzung zu verwenden. Einzelheiten finden Sie unterProgramSelector
.Um Leistungs- oder Binder-bezogene Probleme zu vermeiden, muss der MediaBrowser-Dienst Paginierung unterstützen:
-
EXTRA_PAGE
-
EXTRA_PAGE_SIZE
- Zusätzliche Parameter für
subscribe()
Hinweis: Standardmäßig wird die Paginierung standardmäßig in der Variante
onLoadChildren()
ohne Optionenbehandlung implementiert.Verwandte Einträge aus allen Arten von Listen (Rohkanäle, gefundene Programme und Favoriten) können unterschiedliche mediaIds haben (es liegt an der Radio-App; die Support-Bibliothek wird sie unterschiedlich haben). Die URIs (in ProgramSelector-Form) unterscheiden sich in den meisten Fällen zwischen Rohkanälen und gefundenen Programmen (außer bei FM ohne RDS), sind aber zwischen gefundenen Programmen und Favoriten meistens gleich (außer zum Beispiel, wenn AF aktualisiert wurde).
Durch unterschiedliche mediaIds für Einträge aus unterschiedlichen Listentypen können unterschiedliche Aktionen mit ihnen durchgeführt werden. Sie können entweder die Favoritenliste oder die Liste Alle Programme auf
onSkipToNext
, je nach Ordner des zuletzt ausgewähltenMediaItem
(siehe MediaSession ).Spezielle Tune-Aktionen
Die Programmliste ermöglicht es Benutzern, auf einen bestimmten Sender abzustimmen, erlaubt Benutzern jedoch nicht, allgemeine Anfragen wie "Auf FM einstellen" zu stellen, was dazu führen könnte, dass auf einen kürzlich gehörten Sender auf dem FM-Band eingestellt wird.
Um solche Aktionen zu unterstützen, haben einige Verzeichnisse der obersten Ebene das Flag
FLAG_PLAYABLE
gesetzt (zusammen mitFLAG_BROWSABLE
für Ordner).Handlung Stimmt zu Wie ausstellen Radio spielen Jeder Funkkanal startService(ACTION_PLAY_BROADCASTRADIO)
oder,
playFromMediaId(MediaBrowser. getRoot() )
FM abspielen Jeder UKW-Kanal Spielen Sie von der mediaId
des UKW-Bands ab.Die Bestimmung, welches Programm eingestellt werden soll, liegt bei der App. Dies ist normalerweise der zuletzt eingestellte Kanal aus der gegebenen Liste. Einzelheiten zu
ACTION_PLAY_BROADCASTRADIO
finden Sie unter Allgemeine Wiedergabeabsichten .Erkennung und Serviceverbindung
PackageManager
kann den MediaBrowserService, der den Broadcast-Radio-Baum bereitstellt, direkt finden. RufenresolveService
mit der AbsichtACTION_PLAY_BROADCASTRADIO
(siehe Allgemeine Wiedergabeabsichten ) und dem FlagMATCH_SYSTEM_ONLY
. VerwendenqueryIntentServices
, um alle Dienste zu finden, die Radio bereitstellen (es kann mehr als einen geben, z. B. separate AM/FM und Satellit).Der aufgelöste Dienst verarbeitet auch die
android.media.browse.MediaBrowserService
. Dies wird mit GTS verifiziert.Um eine Verbindung mit dem ausgewählten MediaBrowserService herzustellen, erstellen Sie eine
MediaBrowser
Instanz für eine bestimmte Dienstkomponente undconnect
Sie . Nach dem Verbindungsaufbau kann übergetSessionToken
ein Handle auf MediaSession bezogen werden.Die Radio-App kann Client-Pakete einschränken, die in einer
onGetRoot
-Implementierung ihres Dienstes eine Verbindung herstellen dürfen. Die App sollte es System-Apps ermöglichen, sich ohne Whitelist zu verbinden. Weitere Informationen zum Whitelisting finden Sie unter Paket und Signatur der Assistant-App akzeptieren .Wenn die quellenspezifische App (z. B. eine Radio-App) auf einem Gerät ohne eine solche Quellenunterstützung installiert ist, würde sie sich immer noch so ausgeben, dass sie die Absicht
ACTION_PLAY_BROADCASTRADIO
, aber ihre MediaBrowser-Struktur würde keine radiospezifischen Tags enthalten. Daher muss ein Client, der prüfen möchte, ob eine bestimmte Quelle auf einem Gerät verfügbar ist, Folgendes tun:- Entdecken Sie den Radiodienst (rufen
resolveService
fürACTION_PLAY_BROADCASTRADIO
auf). - Erstellen Sie
MediaBrowser
und stellen Sie dann eine Verbindung her. - Bestimmen Sie das Vorhandensein von
MediaItem
mitEXTRA_BCRADIO_FOLDER_TYPE
extra.
Hinweis: In den meisten Fällen muss der Client alle verfügbaren MediaBrowser-Bäume scannen, um alle verfügbaren Quellen für ein bestimmtes Gerät zu erkennen.
Bandnamen
Die Bandliste wird durch eine Reihe von Verzeichnissen der obersten Ebene mit einem Ordnertyp-Tag dargestellt, das auf
BCRADIO_FOLDER_TYPE_BAND
. Die Titel ihrerMediaItem
sind lokalisierte Zeichenfolgen, die Bandnamen darstellen. In den meisten Fällen wird es sich um eine englische Übersetzung handeln, aber der Kunde kann sich nicht darauf verlassen.Um einen stabilen Mechanismus zum Suchen bestimmter Bands bereitzustellen, wird ein zusätzliches Tag für Bandordner hinzugefügt,
EXTRA_BCRADIO_BAND_NAME_EN
. Dies ist ein nicht lokalisierter Name der Band und kann nur einen dieser vordefinierten Werte annehmen:-
AM
-
FM
-
DAB
Wenn sich die Band nicht auf dieser Liste befindet, sollte das Bandnamen-Tag nicht gesetzt werden. Wenn sich die Band jedoch auf der Liste befindet, muss für sie ein Tag festgelegt sein. HD-Radio zählt keine separaten Bänder auf, da es dasselbe zugrunde liegende Medium wie AM/FM verwendet.
Allgemeine Spielabsichten
Jede App, die für die Wiedergabe einer bestimmten Quelle (wie Radio oder CD) bestimmt ist, muss eine allgemeine Wiedergabeabsicht verarbeiten, um mit der Wiedergabe von Inhalten zu beginnen, möglicherweise aus einem inaktiven Zustand (z. B. nach dem Booten). Es liegt an der App, wie sie den abzuspielenden Inhalt auswählt, aber in der Regel handelt es sich um das zuletzt abgespielte Radioprogramm oder den CD-Titel. Für jede Audioquelle ist ein separater Intent definiert:
-
android.car.intent.action.PLAY_BROADCASTRADIO
-
android.car.intent.action.PLAY_AUDIOCD
: CD-DA oder CD-Text -
android.car.intent.action.PLAY_DATADISC
: Optische Datendisc wie CD/DVD, aber keine CD-DA (möglicherweise Mixed-Mode-CD) -
android.car.intent.action.PLAY_AUX
: Ohne Angabe des AUX-Ports -
android.car.intent.action.PLAY_BLUETOOTH
-
android.car.intent.action.PLAY_USB
: Ohne Angabe des USB-Geräts -
android.car.intent.action.PLAY_LOCAL
: Lokaler Medienspeicher (integrierter Flash)
Absichten wurden ausgewählt, um für allgemeine Wiedergabebefehle verwendet zu werden, da sie zwei Probleme gleichzeitig lösen: den allgemeinen Wiedergabebefehl selbst und die Diensterkennung. Ein zusätzlicher Vorteil einer solchen Absicht wäre die Möglichkeit, eine solche einfache Aktion auszuführen, ohne eine MediaBrowser-Sitzung zu öffnen.
Service Discovery ist eigentlich das wichtigere Problem, das mit diesen Absichten gelöst wird. Das Verfahren zur Diensterkennung ist auf diese Weise einfach und eindeutig (siehe Erkennung und Dienstverbindung ).
Um einige Client-Implementierungen zu vereinfachen, gibt es eine alternative Möglichkeit, einen solchen Play-Befehl auszugeben (der auch von der Radio-App implementiert werden muss): Ausgeben von
playFromMediaId
mit der rootId des Root-Knotens (als mediaId verwendet). Während der Root-Knoten nicht abspielbar sein soll, ist seine rootId eine beliebige Zeichenfolge, die als mediaId konsumierbar gemacht werden kann. Kunden müssen diese Nuance jedoch nicht verstehen.ProgramSelector
Während
mediaId
ausreicht, um einen Kanal aus demMediaBrowserService
, wird es an eine Sitzung gebunden und zwischen den Anbietern nicht konsistent. In einigen Fällen benötigt der Client möglicherweise einen absoluten Zeiger (z. B. eine absolute Häufigkeit), um ihn zwischen Sitzungen und Geräten beizubehalten.Im Zeitalter digitaler Radiosendungen reicht eine reine Frequenz nicht aus, um einen bestimmten Sender einzustellen. Stellen Sie daher mit
ProgramSelector
einen analogen oder digitalen Kanal ein.ProgramSelector
besteht aus zwei Teilen:- Primäre Kennung. Eine eindeutige und stabile Kennung für einen bestimmten Radiosender, die sich nicht ändert, aber möglicherweise nicht ausreicht, um diesen Sender einzustellen. Zum Beispiel RDS PI-Code, der in den USA in das Rufzeichen übersetzt werden kann.
- Sekundäre Identifikatoren. Zusätzliche Identifikatoren, die zum Einstellen auf diesen Sender nützlich sind (z. B. Frequenz), möglicherweise einschließlich Identifikatoren von anderen Funktechnologien. Beispielsweise kann ein DAB-Sender einen analogen Rundfunk-Fallback haben.
Damit
ProgramSelector
in dieMediaBrowser
oderMediaSession
basierte Lösung passt, definieren Sie ein URI-Schema, um es zu serialisieren. Das Schema ist wie folgt definiert:broadcastradio://program/<primary ID type>/<primary ID>? <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
In diesem Beispiel ist der sekundäre Bezeichner-Teil (nach dem Fragezeichen (
?
)) optional und kann entfernt werden, um einen stabilen Bezeichner zur Verwendung alsmediaId
. Zum Beispiel:-
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
Der Behördenteil (AKA-Host) des
program
bietet Raum für zukünftige Systemerweiterungen. Die Zeichenfolgen des Bezeichnertyps werden genau als ihre Namen in der HAL 2.x-Definition vonIdentifierType
angegeben, und das Wertformat ist eine Dezimal- oder Hexadezimalzahl (mit0x
-Präfix).Alle herstellerspezifischen Bezeichner werden durch das Präfix
VENDOR_
. Beispiel:VENDOR_0
fürVENDOR_START
undVENDOR_1
fürVENDOR_START
plus 1. Solche URIs sind spezifisch für die Funkhardware, auf der sie generiert wurden, und können nicht zwischen Geräten verschiedener OEMs übertragen werden.Diese URIs müssen jedem MediaItem unter den Radioordnern der obersten Ebene zugewiesen werden. Darüber hinaus muss die MediaSession sowohl
playFromMediaId
als auchplayFromUri
. Der URI ist jedoch in erster Linie für die Extraktion von Radiometadaten (z. B. FM-Frequenz) und die dauerhafte Speicherung vorgesehen. Es gibt keine Garantie, dass der URI für alle Medienelemente verfügbar ist (z. B. wenn der primäre ID-Typ noch nicht vom Framework unterstützt wird). Andererseits funktioniert Media ID immer. Es wird nicht empfohlen , dass Clients URI verwenden, um Elemente aus der aktuellen MediaBrowser-Sitzung auszuwählen. Verwenden Sie stattdessenplayFromMediaId
. Allerdings ist es für die Serving-App nicht optional, und fehlende URIs sind für gut begründete Fälle reserviert.Das ursprüngliche Design verwendete einen einzelnen Doppelpunkt anstelle der
://
Sequenz nach dem Schemateil. Ersteres wird jedoch vonandroid.net.Uri
für absolute hierarchische URI-Referenzen nicht unterstützt.Andere Quelltypen
Andere Audioquellen können ähnlich gehandhabt werden. Zum Beispiel AUX-Eingang und der Audio-CD-Player.
Eine einzelne App kann mehrere Arten von Quellen bedienen. In solchen Fällen wird empfohlen , für jeden Quellentyp einen separaten MediaBrowserService zu erstellen. Selbst in einer Einrichtung mit mehreren bereitgestellten Quellen/MediaBrowserServices wird dringend empfohlen , eine einzelne MediaSession in einer einzelnen App zu haben.
Audio-CD
Ähnlich wie bei Audio-CDs würde die App, die solche Datenträger bereitstellt, MediaBrowser mit einem einzigen durchsuchbaren Eintrag (oder mehr, wenn das System über einen CD-Wechsler verfügt) verfügbar machen, der wiederum alle Titel einer bestimmten CD enthalten würde. Wenn das System die Tracks auf jeder CD nicht kennt (z. B. wenn alle Datenträger gleichzeitig in eine Kassette eingelegt sind und nicht alle gelesen werden), wäre MediaItem für den gesamten Datenträger nur
PLAYABLE
, nichtBROWSABLE
plusPLAYABLE
. Wenn sich in einem bestimmten Steckplatz keine Diskette befindet, wäre das Element wederPLAYABLE
nochBROWSABLE
(aber jeder Steckplatz muss immer im Baum vorhanden sein).Abbildung 3. Audio-CD-Baumstruktur Diese Einträge würden auf ähnliche Weise wie Rundfunkordner gekennzeichnet; Sie würden zusätzliche zusätzliche Felder enthalten, die in der MediaDescription-API definiert sind:
-
EXTRA_CD_TRACK
: Für jedesMediaItem
auf Audio-CD, 1-basierte Titelnummer. -
EXTRA_CD_DISK
: 1-basierte Plattennummer.
Für ein CD-Text-fähiges System und eine kompatible Platte hätte das MediaItem der obersten Ebene einen Titel der Platte. In ähnlicher Weise würden die MediaItems für Tracks einen Titel des Tracks haben.
AUX Eingang
Die App, die Hilfseingaben bereitstellt, macht eine MediaBrowser-Struktur mit einem einzelnen Eintrag (oder mehreren, wenn mehrere Ports vorhanden sind) verfügbar, der den AUX-Eingangsport darstellt. Die jeweilige MediaSession nimmt ihre mediaId und wechselt zu dieser Quelle, nachdem sie die
playFromMediaId
Anforderung erhalten hat.Abbildung 4. AUX-Baumstruktur Jeder AUX-MediaItem-Eintrag hätte ein zusätzliches Feld
EXTRA_AUX_PORT_NAME
, das auf den nicht lokalisierten Namen des Ports ohne die „AUX“-Phrase gesetzt ist. For example, "AUX 1" would have be set to "1", "AUX front" to "front" and "AUX" to an empty string. In non-English locales, the name tag would remain the same English string. Unlikely as forEXTRA_BCRADIO_BAND_NAME_EN
, the values are OEM-defined and not constrained to a predefined list.If the hardware can detect devices connected to the AUX port, the hardware should mark the MediaItem as
PLAYABLE
, only if input is connected. The hardware should still be enumerated (but notPLAYABLE
) if nothing was connected to this port. If the hardware has no such capability, the MediaItem must always be set toPLAYABLE
.Extra fields
Define the following fields:
-
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"
Client needs to review the top-level MediaItems for elements having the
EXTRA_CD_DISK
orEXTRA_AUX_PORT_NAME
extra field set.Detailed examples
The following examples address the MediaBrowser tree structure for source types that are part of this design.
Broadcast radio MediaBrowserService (handles
ACTION_PLAY_BROADCASTRADIO
):- Stations (browsable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
- BBC One (playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
- ABC 88.1 (playable) URI:
broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
- ABC 88.1 HD1 (playable) URI:
broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
- ABC 88.1 HD2 (playable) URI:
broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
- 90.5 FM (playable) – FM without RDSURI:
broadcastradio://program/AMFM_FREQUENCY/90500
- 620 AM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/620
- BBC One (playable) URI:
broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
- BBC One (playable) URI:
- Favorites (browsable, playable)
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
- BBC One (playable) URI:
broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
- BBC Two (not playable)URI:
broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
- BBC One (playable) URI:
- AM (browsable, playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
- 530 AM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/530
- 540 AM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/540
- 550 AM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/550
- 530 AM (playable) URI:
- FM (browsable, playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
- 87.7 FM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87700
- 87.9 FM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/87900
- 88.1 FM (playable) URI:
broadcastradio://program/AMFM_FREQUENCY/88100
- 87.7 FM (playable) URI:
- DAB (playable):
EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"
Audio CD MediaBrowserService (handles
ACTION_PLAY_AUDIOCD
):- Disc 1 (playable)
EXTRA_CD_DISK=1
- Disc 2 (browsable, playable)
EXTRA_CD_DISK=2
- Track 1 (playable)
EXTRA_CD_TRACK=1
- Track 2 (playable)
EXTRA_CD_TRACK=2
- Track 1 (playable)
- My music CD (browsable, playable)
EXTRA_CD_DISK=3
- All By Myself (playable)
EXTRA_CD_TRACK=1
- Reise, Reise (playable)
EXTRA_CD_TRACK=2
- All By Myself (playable)
- Empty slot 4 (not playable)
EXTRA_CD_DISK=4
AUX MediaBrowserService (handles
ACTION_PLAY_AUX
):- AUX front (playable)
EXTRA_AUX_PORT_NAME="front"
- AUX rear (playable)
EXTRA_AUX_PORT_NAME="rear"
-