Funk implementieren

Auf dieser Seite wird erläutert, wie Funk auf Hardware- und Softwareebene implementiert wird.

Systemkomponenten

Der Broadcast-Radio-Stack umfasst die folgenden Komponenten.

Broadcast-Radio-Architektur
Abbildung 1. Broadcast-Radio-Architektur

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 startet, fordert er Radio Manager auf, einen Radio-Tuner zu öffnen. Anschließend kann die App Anfragen an den Radio-Tuner senden, z. B. die Einstellung eines bestimmten Radiosenders oder einer bestimmten Frequenz oder die Suche nach dem nächsten verfügbaren Radiosender. Die App empfängt Aktualisierungen vom Radio Manager und Radio Tuner im Radio, z. B. aktuelle Programminformationen, Radioprogrammlisten, Konfigurationen und vom Hersteller definierte Parameter. Die Referenzradio-App unterstützt nur AM- und FM-Radio. OEMs können die Radio-App nach Wunsch 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 schließt die Sitzung dann in eine ein 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. In Radio Tuner definierte Rückrufmethoden ( RadioTuner.Callback ) senden Aktualisierungen zum Rundfunk-HAL, z. B. aktuelle Programminformationen, Programmlisten und vom Hersteller definierte 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 Radiomanager mit Broadcast Radio HALs. Der Broadcast Radio Service unterstützt Rundfunk-HALs der HAL Interface Definition Language (HIDL) und der Android Interface Definition Language (AIDL) . Der Broadcast Radio Service stellt eine Verbindung zum AIDL HAL her, wenn ein AIDL HAL-Dienst vorhanden ist. Andernfalls wird der Dienst mit dem 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 Radiomanager kann den Broadcast Radio Service auffordern, je nach Radiotyp eine Tuner-Sitzung auf dem entsprechenden Radiomodul zu erstellen. Jede Tuner-Sitzung kann Methoden wie „tune“, „step“ und „cancel“ (definiert in HAL-Schnittstellen) aufrufen, um Vorgänge auf der entsprechenden Rundfunk-HAL-Instanz auszuführen. Wenn eine Tuner-Sitzung einen Rückruf von der HAL-Instanz zu einem HAL-Update erhält, z. B. aktuelle Programminformationen, Programmliste, Konfigurationsflags und Herstellerparameter, werden Rückrufe zum Update an alle Radio-Tuner gesendet, die mit demselben Radiomodul verbunden sind.

Rundfunkradio HAL

Weitere Informationen zu den HIDL- und AIDL-Schnittstellen des Rundfunks und den Unterschieden zwischen beiden finden Sie unter HAL-Schnittstelle für Rundfunk .

Hardware-Abstraktionsschicht für Rundfunk

In den folgenden Abschnitten wird beschrieben, wie Sie mit der Hardware-Abstraktionsschicht (HAL) arbeiten, um Rundfunk zu implementieren.

HAL-Schnittstelle für Rundfunkradio

Der Rundfunkradio-HAL stellt Datenstrukturen und Schnittstellen auf Hardwareebene zur Implementierung von Rundfunkradios wie AM/FM- und DAB-Radio bereit.

HIDL 2.0- und AIDL-Schnittstellen

Das Rundfunkradio HAL nutzt die in den folgenden Abschnitten beschriebenen Schnittstellen.

Ansage-Hörer

IAnnouncementListener ist die Rückrufschnittstelle für den Ansage-Listener, der bei Radio HAL registriert werden kann, um Ansagen zu empfangen. Die Schnittstelle verfügt über die folgenden Methoden:

IAnnouncementListener
Beschreibung: Wird immer dann aufgerufen, wenn sich die Ankündigungsliste geändert hat.
HIDL 2.0 oneway onListUpdated(vec<Announcement> announcements)
AIDL oneway void onListUpdated(in Announcement[] announcements)
Griff schließen

ICloseHandle ist das generische Schließhandle zum Entfernen eines Rückrufs, der keine aktive Schnittstelle benötigt.

ICloseHandle
Beschreibung: Den Griff schließen.
HIDL 2.0 close()
AIDL void close()

Rückrufschnittstelle

ITunerCallback ist die Rückrufschnittstelle, die vom Rundfunksender HAL aufgerufen wird, um Aktualisierungen an den HAL-Clientdienst zu senden.

ITunerCallback
Beschreibung: Wird von der HAL aufgerufen, wenn ein Optimierungsvorgang (Abstimmen, Suchen (in AIDL) oder Scannen (in HIDL) und Schritt erfolgreich) asynchron fehlschlägt.
HIDL 2.0 oneway onCurrentProgramInfoChanged(ProgramInfo info)
AIDL void onCurrentProgramInfoChanged(in ProgramInfo info)
Beschreibung: Wird aufgerufen, wenn die Optimierung, Suche (in AIDL) oder Suche (in HIDL) oder ein Schritt erfolgreich ist.
HIDL 2.0 oneway onTuneFailed(Result result, ProgramSelector selector)
AIDL void onTuneFailed(in Result result, in ProgramSelector selector)
Beschreibung: Wird aufgerufen, wenn die Optimierung, Suche (in AIDL) oder Suche (in HIDL) oder ein Schritt erfolgreich ist.
HIDL 2.0 oneway onCurrentProgramInfoChanged(ProgramInfo info)
AIDL void onCurrentProgramInfoChanged(in ProgramInfo info)
Beschreibung: Wird aufgerufen, wenn die Programmliste aktualisiert wird. Die Größe jedes Blocks sollte auf 500 KB begrenzt sein.
HIDL 2.0 oneway onProgramListUpdated(ProgramListChunk chunk)
AIDL oneway onProgramListUpdated(ProgramListChunk chunk)
Beschreibung: Wird aufgerufen, wenn die Antenne angeschlossen oder getrennt ist.
HIDL 2.0 oneway onAntennaStateChange(bool connected)
AIDL void onCurrentProgramInfoChanged(in ProgramInfo info)
Beschreibung: Wird aufgerufen, wenn die herstellerspezifischen Parameterwerte in HAL intern aktualisiert werden (sollte nicht nach dem Aufruf von setParameters durch den HAL-Client aufgerufen werden).
HIDL 2.0 oneway onParametersUpdated(vec<VendorKeyValue> parameters)
AIDL void onParametersUpdated(in VendorKeyValue[] parameters)
Beschreibung: Neu in AIDL. Wird aufgerufen, wenn das Konfigurationsflag intern in der HAL aktualisiert wird (sollte nicht nach dem Aufruf von setConfigFlag durch den HAL-Client aufgerufen werden).
HIDL 2.0 Unzutreffend.
AIDL void onConfigFlagUpdated(in ConfigFlag flag, in boolean value)

Primäre Rundfunk-HAL-Schnittstelle

IBroadcastRadio ist die primäre Schnittstelle für das Rundfunkradio HAL. Verwenden Sie im 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 verfügt nur über einen Tuner-Chip). ITunerSession wurde aus den AIDL-Schnittstellen entfernt und seine Schnittstellen nach IBroadcastRadio verschoben.

IBroadcastRadio
Beschreibung: Rufen Sie die Beschreibung eines Moduls und seiner Funktionen ab.
HIDL 2.0 getProperties() generates (Properties properties)
AIDL Properties getProperties()
Beschreibung: Ruft die aktuelle oder mögliche AM/FM-Regionskonfiguration ab.
HIDL 2.0 getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config)
AIDL AmFmRegionConfig getAmFmRegionConfig(bool full)
Beschreibung: Ruft die aktuelle DAB-Regionskonfiguration ab.
HIDL 2.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 harten Begrenzung des Binder-Transaktionspuffers weniger als 1 MB betragen.
HIDL 2.0 getImage(uint32_t id) generates (vec<uint8_t> image)
AIDL byte[] getImage(in int id)
Beschreibung: Registriert den Ansage-Listener.
HIDL 2.0 registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle)
AIDL ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled)
Beschreibung:
  • HIDL HAL: Wenn eine neue Tuner-Sitzung geöffnet wird, muss die alte Sitzung beendet werden.
  • AIDL HAL: Da keine Tuner-Sitzung verfügbar ist, muss nur der Tuner-Callback eingestellt werden. Falls vorhanden, sollte der alte Rückruf deaktiviert werden.
HIDL 2.0 openSession(ITunerCallback callback) generiert (Result result, ITunerSession session)
AIDL void setTunerCallback(in ITunerCallback callback)
Beschreibung:
  • HIDL HAL: Das Schließen einer Tuner-Sitzung darf nicht fehlschlagen und darf nur einmal ausgegeben werden.
  • AIDL HAL: Es gibt keinen Tuner und nur der Tuner-Callback muss deaktiviert werden.
HIDL 2.0 close()
AIDL unsetTunerCallback()
Beschreibung: Stellt ein bestimmtes Programm ein.
HIDL 2.0 tune(ProgramSelector program) generates (Result result)
AIDL void tune(in ProgramSelector program)
Beschreibung: Sucht nach dem nächsten gültigen ausgestrahlten Programm. Um Verwirrung in AIDL zu vermeiden, wird scan in seek umbenannt.
HIDL 2.0 scan(bool directionUp, bool skipSubChannel) generates (Result result)
AIDL void seek(in boolean directionUp, in boolean skipSubChannel)
Beschreibung: Schritte zum Nachbarkanal, der von keinem Programm belegt sein darf.
HIDL 2.0 step(bool directionUp) generates (Result result)
AIDL void step(in boolean directionUp)
Beschreibung: Bricht ausstehende Optimierungs-, Scan- (in HIDL) oder Such- (in AIDL) oder Schrittoperationen ab.
HIDL 2.0 cancel()
AIDL void cancel()
Beschreibung: Wendet einen Filter auf die Programmliste an und beginnt mit dem Senden von Programmlistenaktualisierungen über onProgramListUpdated Rückruf.
HIDL 2.0 startProgramListUpdates(ProgramFilter filter) generates (Result result)
AIDL void startProgramListUpdates(in ProgramFilter filter)
Beschreibung: Das Senden von Aktualisierungen der Programmliste wird gestoppt.
HIDL 2.0 stopProgramListUpdates()
AIDL void stopProgramListUpdates()
Beschreibung: Ruft die aktuelle Einstellung eines bestimmten Konfigurationsflags ab.
HIDL 2.0 isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value)
AIDL boolean isConfigFlagSet(in ConfigFlag flag)
Beschreibung: Setzt das angegebene Konfigurationsflag.
HIDL 2.0 setConfigFlag(ConfigFlag flag, bool value) generates (Result result)
AIDL void setConfigFlag(in ConfigFlag flag, boolean value)
Beschreibung: Legt herstellerspezifische Parameterwerte fest.
HIDL 2.0 setParameters(vec<VendorKeyValue> parameters)

erzeugt ,

(vec<VendorKeyValue> results)
AIDL VendorKeyValue[] setParameters(in VendorKeyValue[] parameters)
Beschreibung: Ruft herstellerspezifische Parameterwerte ab.
HIDL 2.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. Optimierung, Scan (in HIDL) oder Suche (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 einplanen später auftreten und schnell einen Status oder ein Ergebnis zurückgeben. Im Einzelnen sollte jeder Vorgang:

  • Brechen Sie alle ausstehenden Tuning-Vorgänge ab.
  • Überprüfen Sie, ob der Vorgang 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 status (in AIDL) zurück. Wenn das Result oder status OK ist, muss der Tuner-Rückruf tuneFailed oder currentProgramInfoChanged aufgerufen werden, wenn die Optimierungsaufgabe fehlgeschlagen ist (z. B. aufgrund einer Zeitüberschreitung) oder abgeschlossen ist.

In ähnlicher Weise plant startProgramListUpdates auch die zeitaufwändige Aufgabe, die Programmliste zu einem späteren Zeitpunkt zu aktualisieren und schnell einen Status oder ein Ergebnis zurückzugeben. Die Methode bricht zunächst ausstehende Aktualisierungsanfragen ab, plant dann die Aktualisierungsaufgabe und gibt das Ergebnis schnell zurück.

Rennbedingung

Aufgrund des asynchronen Verhaltens von Optimierungsvorgängen (z. B. „Tune“, „Scan“ (in HIDL) oder „Seek“ (in AIDL) und „Step“) besteht eine Wettlaufbedingung zwischen dem Abbrechen des Vorgangs und den Optimierungsvorgängen. Wenn cancel aufgerufen wird, nachdem HAL einen Optimierungsvorgang abgeschlossen hat und bevor der Rückruf abgeschlossen ist, kann „Cancel“ 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 ebenfalls ignoriert werden und der Rückruf sollte abgeschlossen werden.

Beschränkung der Datengröße

Da es eine feste Grenze für den Binder-Transaktionspuffer gibt, wird die Datengrenze für einige Schnittstellenmethoden, die potenziell große Daten weitergeben, in der AIDL-HAL klargestellt.

  • getImage ist es erforderlich, dass das zurückgegebene Bild weniger als 1 MB groß ist.
  • onProgramListUpdate erfordert, dass jeder chunk weniger als 500 KB groß ist. Größere Programmlisten müssen von der HAL-Implementierung in mehrere Blöcke aufgeteilt und über mehrere Rückrufe gesendet werden.

Änderungen in AIDL HAL-Datenstrukturen

Zusätzlich zu den Änderungen an den Schnittstellen wurden diese Änderungen auf die im Rundfunk-AIDL HAL definierten Datenstrukturen angewendet, die die Vorteile von AIDL nutzen.

  • Die Constant Aufzählung wird in AIDL entfernt und in IBroadcastRadio als const int definiert. In der Zwischenzeit wird ANTENNA_DISCONNECTED_TIMEOUT_MS in ANTENNA_STATE_CHANGE_TIMEOUT_MS umbenannt. Eine neue Konstante int TUNER_TIMEOUT_MS wird hinzugefügt. Alle Abstimmungs-, Such- und Schrittvorgänge müssen innerhalb dieser Zeit abgeschlossen sein.
  • Enum RDS und Deemphasis werden in AIDL entfernt und als const int in AmFmRegionConfig definiert. Dementsprechend werden sowohl fmDeemphasis als auch fmRds in ProgramInfo als int deklariert, ein Bitberechnungsergebnis der jeweiligen Flags. Inzwischen werden D50 und D75 in DEEMPHASIS_D50 bzw. DEEMPHASIS_D75 umbenannt.
  • Enum ProgramInfoFlags werden in AIDL entfernt und als const int in ProgramInfo mit einem hinzugefügten Präfix FLAG_ definiert. Dementsprechend werden infoFlags in ProgramInfo als int deklariert, ein Bitberechnungsergebnis von Flags. TUNED wird außerdem in FLAG_TUNABLE umbenannt, um die Definition, auf die der Sender eingestellt werden kann, besser zu beschreiben.
  • In AmFmBandRange wird scanSpacing in seekSpacing “ umbenannt, da „ scan in AIDL in „ seek umbenannt wird.
  • Da das Konzept der Vereinigung in AIDL eingeführt wurde, werden MetadataKey und Metadata die in HIDL HAL definiert sind, nicht mehr verwendet. AIDL-Union Metadata werden in AIDL HAL definiert. Jeder Enumerationswert, der zuvor in MetadataKey enthalten war, ist jetzt ein Feld in Metadata 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 Implementierung des Mediensuchbaums wird in der Bibliothek car-broadcastradio-support in packages/apps/Car/libs bereitgestellt. Diese Bibliothek enthält auch Erweiterungen von ProgramSelector zum Konvertieren in und von URI. Es wird empfohlen, dass Radioimplementierungen diese Bibliothek verwenden, um den zugehörigen Suchbaum zu erstellen.

Medienquellen-Umschalter

Um einen nahtlosen Übergang zwischen Radio und anderen in Medien angezeigten Apps zu ermöglichen, enthält die car-media-common-Bibliothek Klassen, die in die Radio-App integriert werden sollen. MediaAppSelectorWidget kann in das XML für die Radio-App eingefügt 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 der 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 unter packages/apps/Car/Radio befindet.

Detaillierte Kontrollspezifikationen

Die MediaSession Schnittstelle (über MediaSession.Callback ) bietet Steuerungsmechanismen für das aktuell wiedergegebene Radioprogramm:

  • onPlay , onStop . Stummschaltung der Radiowiedergabe aufheben.
  • onPause . Zeitversetzte Pause (sofern unterstützt).
  • onPlayFromMediaId . Spielen Sie beliebige Inhalte aus einem Ordner der obersten Ebene ab. Zum Beispiel „FM abspielen“ oder „Radio abspielen“.
  • onPlayFromUri . Spielen Sie eine bestimmte Frequenz. Beispiel: „Spielen Sie 88,5 FM.“
  • onSkipToNext , onSkipToPrevious . Stellen Sie einen nächsten oder vorherigen Sender ein.
  • onSetRating . Zu Favoriten hinzufügen oder daraus entfernen.

Der MediaBrowser stellt ein anpassbares MediaItem über drei Arten von Verzeichnissen der obersten Ebene bereit:

  • ( Optional ) Programme (Sender). Dieser Modus wird typischerweise von Dual-Tuner-Radios verwendet, um alle verfügbaren abstimmbaren Radiosender am Standort des Benutzers anzuzeigen.
  • Favoriten. Zur Favoritenliste hinzugefügte Radioprogramme, einige 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 verfügt über ein eigenes Top-Level-Verzeichnis.
MediaBrowserService-Baumstruktur
Abbildung 2. MediaBrowserService-Baumstruktur

Jedes Element in jedem dieser Ordner (AM/FM/Programme) ist ein MediaItem mit einem URI, das mit MediaSession zur Optimierung 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“ allesamt unspezifische Radioabfragen, die eine mediaId verwenden, um sie an die OEM-Radio-App zu senden. Es liegt an der Radio-App, anhand der generischen Anfrage und der mediaId zu bestimmen, was abgespielt werden soll.

Mediensitzung

Da es kein Konzept zum Anhalten eines Sendestreams gibt, gelten die Aktionen „Wiedergabe“, „Pause“ und „Stopp“ 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 Pause des Sendestreams zu simulieren, indem Inhalte zwischengespeichert und später wiedergegeben werden. Verwenden Sie in solchen Fällen onPause .

Das Abspielen von mediaId- und URI-Aktionen soll dazu dienen, einen Sender anzuhören, der von der MediaBrowser-Schnittstelle abgerufen wurde. Die mediaId ist eine beliebige Zeichenfolge, die von der Radio-App bereitgestellt wird, um einen eindeutigen (eine bestimmte ID verweist also nur auf ein Element) und einen stabilen (ein bestimmtes Element hat während der gesamten Sitzung dieselbe ID) Wert festzulegen, mit dem ein bestimmter Sender identifiziert werden kann . Der URI hat ein klar definiertes Schema. Kurz gesagt, eine URI-isierte Form von ProgramSelector. Während dadurch die Eindeutigkeitseigenschaft erhalten bleibt, muss sie nicht stabil sein, obwohl sie sich ändern kann, wenn die Station auf eine andere Frequenz wechselt.

onPlayFromSearch wird konstruktionsbedingt nicht verwendet. Es liegt in der Verantwortung des Clients (Begleit-App), ein Suchergebnis aus der MediaBrowser-Struktur auszuwählen. Die Verlagerung dieser Verantwortung auf die Radio-App würde die Komplexität erhöhen, formelle Verträge darüber erfordern, wie Zeichenfolgenabfragen aussehen sollen, und zu einer ungleichmäßigen Benutzererfahrung auf verschiedenen Hardwareplattformen führen.

Hinweis: Die Radio-App enthält keine zusätzlichen Informationen, die für die Suche nach einem Sendernamen nützlich wären, 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.
  • Wenn Sie einen Sender aus der Programmliste anhören, wird möglicherweise der nächste verfügbare Sender eingestellt, sortiert nach der Kanalnummer.
  • Das Anhören eines beliebigen Kanals kann dazu führen, dass auf den nächsten physischen Kanal umgeschaltet wird, selbst wenn kein Sendesignal vorhanden ist.

Die Radio-App übernimmt diese Aktionen.

Fehlerbehandlung

TransportControls Aktionen (Wiedergabe, Stopp und Weiter) geben kein Feedback darüber, ob die Aktion erfolgreich ist 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 Fehlerstatus festlegen. Wenn die Ausführung des Wiedergabebefehls nicht sofort erfolgt, sollte der Wiedergabestatus während der Ausführung des Befehls in STATE_CONNECTING (bei direkter Abstimmung) oder STATE_SKIPPING_TO_PREVIOUS oder NEXT geändert werden.

Der Client sollte den PlaybackState beobachten und überprüfen, ob die Sitzung das aktuelle Programm in den angeforderten Zustand 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 erfolgen.

Favoriten hinzufügen und entfernen

MediaSession verfügt über eine Bewertungsunterstützung, mit der Favoriten gesteuert werden können. Der Aufruf onSetRating mit einer Bewertung vom Typ RATING_HEART fügt den aktuell eingestellten Sender zur Favoritenliste hinzu oder entfernt ihn daraus.

Im Gegensatz zu älteren Voreinstellungen geht dieses Modell von einer ungeordneten und unbegrenzten Favoritenliste aus, bei der jeder gespeicherte Favorit einem numerischen Feld (normalerweise 1 bis 6) zugewiesen wurde. Infolgedessen wären voreingestellte Systeme nicht mit dem onSetRating Vorgang kompatibel.

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 lediglich eine Einschränkung des MediaBrowser-Clients, beispielsweise einer Begleit-App. Die Radio-App unterliegt keinen derartigen Einschränkungen. Dieser Teil ist optional, wenn eine App keine Favoriten unterstützt.

MediaBrowser

Um auszudrücken, welche Frequenzen oder physikalischen Kanalnamen (wenn die Abstimmung 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 sind dies 101 FM-Kanäle im Bereich von 87,8 bis 108,0 MHz (mit einem Abstand von 0,2 MHz) und 117 AM-Kanäle im Bereich von 530 bis 1700 kHz (mit einem Abstand von 10 kHz). Da HD-Radio denselben Kanalraum nutzt, wird es nicht separat dargestellt.

Die Liste der derzeit verfügbaren Radioprogramme ist flach, da Anzeigeschemata wie die Gruppierung nach DAB-Ensemble (Direct Audio Broadcast) nicht möglich sind.

Einträge in der Favoritenliste können möglicherweise nicht angepasst werden. Zum Beispiel, wenn ein bestimmtes Programm außerhalb des zulässigen Bereichs liegt. Die Radio-App erkennt möglicherweise bereits im Voraus, ob der Eintrag eingestellt werden kann. Wenn dies der Fall ist, wird der Eintrag möglicherweise nicht als spielbar markiert.

Um Ordner der obersten Ebene zu identifizieren, wird der gleiche Mechanismus wie bei Bluetooth angewendet. Das heißt, ein Extras-Bundle des MediaDescription Objekts enthält ein Tuner-spezifisches Feld, genau wie Bluetooth es mit EXTRA_BT_FOLDER_TYPE tut. 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 . Derzeit 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 .
    • FM-Frequenz. URI (siehe ProgramSelector ) oder MediaDescription.getTitle (wenn sich ein Eintrag im Ordner BROADCASTRADIO_FOLDER_TYPE_BAND befindet).
    • Radiospezifische Kennungen (RDS PI, DAB SId). MediaDescription.getMediaUri wird in ProgramSelector analysiert.

    Normalerweise ist es nicht erforderlich, die FM-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 bestehen (z. B. zu Anzeigezwecken), ist er im URI vorhanden und kann in ProgramSelector analysiert werden. Es wird jedoch nicht empfohlen, den URI zum Auswählen von Elementen innerhalb der aktuellen Sitzung zu verwenden. Einzelheiten finden Sie unter ProgramSelector .

    Um Leistungs- oder Ordnerprobleme zu vermeiden, muss der MediaBrowser-Dienst die Paginierung unterstützen:

    Hinweis: Standardmäßig wird die Paginierung standardmäßig in der Variante onLoadChildren() ohne Optionsbehandlung implementiert.

    Verwandte Einträge aus allen Arten von Listen (Rohkanäle, gefundene Programme und Favoriten) können unterschiedliche Medien-IDs 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 jedoch zwischen gefundenen Programmen und Favoriten größtenteils gleich (außer beispielsweise, als AF aktualisiert wurde).

    Durch unterschiedliche Medien-IDs für Einträge aus verschiedenen Listentypen ist es möglich, unterschiedliche Aktionen für diese durchzuführen. Sie können entweder die Favoritenliste oder die Liste „Alle Programme“ auf onSkipToNext durchsuchen, abhängig vom Ordner des zuletzt ausgewählten MediaItem (siehe MediaSession ).

    Spezielle Tune-Aktionen

    Mit der Programmliste können Benutzer einen bestimmten Sender einstellen, aber keine allgemeinen Anfragen wie „FM einstellen“ stellen, was dazu führen könnte, dass ein kürzlich gehörter Sender im UKW-Band eingestellt wird.

    Um solche Aktionen zu unterstützen, ist in einigen Verzeichnissen der obersten Ebene das Flag FLAG_PLAYABLE gesetzt (zusammen mit FLAG_BROWSABLE für Ordner).

    Aktion Melodien zu So stellen Sie es aus
    Radio spielen Jeder Radiosender startService(ACTION_PLAY_BROADCASTRADIO)

    oder

    playFromMediaId(MediaBrowser. getRoot() )
    Spielen Sie UKW Jeder FM-Kanal Spielen Sie von der mediaId des FM-Bands.

    Die Entscheidung, welches Programm eingestellt werden soll, obliegt der App. Dies ist normalerweise der zuletzt eingestellte Kanal aus der angegebenen Liste. Einzelheiten zu ACTION_PLAY_BROADCASTRADIO finden Sie unter Allgemeine Spielabsichten .

    Discovery- und Service-Verbindung

    PackageManager kann den MediaBrowserService, der den Broadcast-Radio-Baum bereitstellt, direkt finden. Rufen Sie dazu resolveService mit der Absicht ACTION_PLAY_BROADCASTRADIO “ (siehe „Allgemeine Spielabsichten “) und dem Flag „ MATCH_SYSTEM_ONLY “ auf. Verwenden Sie queryIntentServices um alle Dienste zu finden, die Radio bereitstellen (es kann mehr als einen geben, z. B. getrennte AM/FM- und Satellitendienste).

    Der aufgelöste Dienst verarbeitet auch die Bindungsabsicht android.media.browse.MediaBrowserService . Dies wird mit GTS überprüft.

    Um eine Verbindung zum ausgewählten MediaBrowserService herzustellen, erstellen Sie MediaBrowser Instanz für eine bestimmte Dienstkomponente und connect . Nach dem Verbindungsaufbau kann über getSessionToken ein Handle zu MediaSession abgerufen 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, eine Verbindung ohne Whitelisting herzustellen. Einzelheiten zum Whitelisting finden Sie unter Akzeptieren des Assistant-App-Pakets und der Signatur .

    Wenn die quellenspezifische App (z. B. eine Radio-App) auf einem Gerät ohne solche Quellenunterstützung installiert wird, würde sie sich immer noch als die Absicht ACTION_PLAY_BROADCASTRADIO verarbeitend ankündigen, ihr MediaBrowser-Baum würde jedoch keine radiospezifischen Tags enthalten. Daher muss ein Client, der prüfen möchte, ob eine bestimmte Quelle auf einem Gerät verfügbar ist:

    1. Entdecken Sie den Radiodienst (rufen Sie resolveService für ACTION_PLAY_BROADCASTRADIO auf).
    2. Erstellen Sie MediaBrowser und stellen Sie dann eine Verbindung her.
    3. Bestimmen Sie das Vorhandensein von MediaItem mit dem Zusatz EXTRA_BCRADIO_FOLDER_TYPE .

    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 dargestellt, wobei das Ordnertyp-Tag auf BCRADIO_FOLDER_TYPE_BAND festgelegt ist. Die Titel ihrer MediaItem sind lokalisierte Zeichenfolgen, die Bandnamen darstellen. In den meisten Fällen handelt es sich um dasselbe wie eine englische Übersetzung, aber der Kunde kann sich nicht auf diese Annahme verlassen.

    Um einen stabilen Mechanismus zum Nachschlagen bestimmter Bands bereitzustellen, wird ein zusätzlicher Tag für Bandordner hinzugefügt, EXTRA_BCRADIO_BAND_NAME_EN . Dies ist ein nicht lokalisierter Name des Bandes und kann nur einen dieser vordefinierten Werte annehmen:

    • AM
    • FM
    • DAB

    Wenn die Band nicht auf dieser Liste steht, sollte das Bandnamen-Tag nicht gesetzt werden. Wenn das Band jedoch auf der Liste steht, muss 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 (z. B. Radio oder CD) vorgesehen ist, muss eine allgemeine Wiedergabeabsicht verarbeiten, um die Wiedergabe einiger Inhalte möglicherweise aus dem inaktiven Zustand (z. B. nach dem Booten) zu starten. Es liegt an der App, wie sie den abzuspielenden Inhalt auswählt, in der Regel handelt es sich jedoch um das zuletzt gespielte Radioprogramm oder den zuletzt gespielten CD-Titel. Für jede Audioquelle ist eine separate Absicht 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 Daten-CD wie CD/DVD, aber nicht CD-DA (möglicherweise eine 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 für die Verwendung für allgemeine Spielbefehle ausgewählt, da sie zwei Probleme gleichzeitig lösen: den allgemeinen Spielbefehl 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.

    Tatsächlich ist die Serviceerkennung das wichtigere Problem, das mit diesen Absichten gelöst wird. Das Verfahren zur Diensterkennung ist auf diese Weise einfach und eindeutig (siehe Erkennung und Dienstanbindung ).

    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): Ausgabe von playFromMediaId mit der Root-ID des Root-Knotens (wird als mediaId verwendet). Während der Root-Knoten nicht abspielbar sein soll, ist seine Root-ID eine beliebige Zeichenfolge, die als mediaId konsumierbar gemacht werden kann. Allerdings ist es für Kunden nicht erforderlich, diese Nuance zu verstehen.

    Programmauswahl

    Während mediaId ausreicht, um einen Kanal aus MediaBrowserService auszuwählen, wird es an eine Sitzung gebunden und ist zwischen 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 aufrechtzuerhalten.

    Im Zeitalter der digitalen Radioübertragung reicht eine bloße Frequenz nicht aus, um einen bestimmten Sender einzustellen. Verwenden Sie daher ProgramSelector um einen analogen oder digitalen Kanal einzustellen. ProgramSelector besteht aus zwei Teilen:

    • Primärer Bezeichner. 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 Bezeichner. Zusätzliche Kennungen, die zum Einstellen dieses Senders nützlich sind (z. B. Frequenz), möglicherweise einschließlich Kennungen anderer Radiotechnologien. Beispielsweise kann ein DAB-Sender über einen analogen Ausweichsender verfügen.

    Damit ProgramSelector in die MediaBrowser oder MediaSession -basierte Lösung passt, definieren Sie ein URI-Schema zur Serialisierung. 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 Bezeichnerteil (nach dem Fragezeichen ( ? )) optional und kann entfernt werden, um einen stabilen Bezeichner für die Verwendung als mediaId bereitzustellen. 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 Autoritätsteil (auch bekannt als Host) des program bietet Raum für zukünftige Programmerweiterungen. Die Zeichenfolgen des Bezeichnertyps werden genau als ihre Namen in der HAL 2.x-Definition von IdentifierType angegeben und das Wertformat ist eine dezimale oder hexadezimale Zahl (mit 0x Präfix).

    Alle herstellerspezifischen Kennungen werden durch das Präfix VENDOR_ dargestellt. Zum Beispiel VENDOR_0 für VENDOR_START und VENDOR_1 für VENDOR_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 in den Radioordnern der obersten Ebene zugewiesen werden. Darüber hinaus muss die MediaSession sowohl playFromMediaId als auch playFromUri unterstützen. Der URI ist jedoch in erster Linie für die Extraktion von Funkmetadaten (z. B. FM-Frequenz) und die dauerhafte Speicherung gedacht. Es gibt keine Garantie dafür, 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 stattdessen playFromMediaId . Allerdings ist dies für die Serving-App nicht optional und fehlende URIs sind nur in begründeten Fällen vorbehalten.

    Im ursprünglichen Entwurf wurde nach dem Schemateil ein einzelner Doppelpunkt anstelle der :// Sequenz verwendet. Ersteres wird jedoch von android.net.Uri für absolute hierarchische URI-Referenzen nicht unterstützt.

    Andere Quellentypen

    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 Quelltyp einen separaten MediaBrowserService zu erstellen. Selbst in einem Setup mit mehreren bereitgestellten Quellen/MediaBrowserServices wird dringend empfohlen , eine einzige MediaSession innerhalb einer einzelnen App zu haben.

    Audio-CD

    Ähnlich wie bei Audio-CDs würde die App, die solche Datenträger bedient, MediaBrowser mit einem einzigen durchsuchbaren Eintrag (oder mehreren, wenn das System über einen CD-Wechsler verfügt) bereitstellen, der wiederum alle Titel einer bestimmten CD enthalten würde. Wenn das System nicht über die Titel auf jeder CD informiert ist (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 lediglich PLAYABLE und nicht BROWSABLE und PLAYABLE . Wenn sich in einem bestimmten Steckplatz kein Datenträger befindet, wäre das Element weder PLAYABLE noch BROWSABLE (aber jeder Steckplatz muss immer im Baum vorhanden sein).

    Baumstruktur der Audio-CD
    Abbildung 3. Baumstruktur der Audio-CD

    Diese Einträge würden auf ähnliche Weise gekennzeichnet wie Rundfunkordner. Sie würden zusätzliche zusätzliche Felder enthalten, die in der MediaDescription-API definiert sind:

    • EXTRA_CD_TRACK : Für jedes MediaItem auf einer Audio-CD, 1-basierte Titelnummer.
    • EXTRA_CD_DISK : 1-basierte Festplattennummer.

    Bei CD-Text-fähigen Systemen und kompatiblen Datenträgern hätte das MediaItem der obersten Ebene einen Titel des Datenträgers. Ebenso hätten die MediaItems für Titel einen Titel des Titels.

    AUX Eingang

    Die App, die Hilfseingaben bereitstellt, stellt einen MediaBrowser-Baum mit einem einzelnen Eintrag (oder mehreren, wenn mehrere Ports vorhanden sind) bereit, der den AUX-In-Port darstellt. Die jeweilige MediaSession nimmt ihre mediaId und wechselt zu dieser Quelle, nachdem sie die playFromMediaId -Anfrage erhalten hat.

    AUX-Baumstruktur
    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 Phrase „AUX“ gesetzt wäre. Beispielsweise wäre „AUX 1“ auf „1“, „AUX front“ auf „front“ und „AUX“ auf eine leere Zeichenfolge gesetzt worden. In nicht-englischen Gebietsschemas würde das Namens-Tag dieselbe englische Zeichenfolge bleiben. Es ist EXTRA_BCRADIO_BAND_NAME_EN , dass die Werte oem definiert und nicht auf eine vordefinierte Liste beschränkt sind.

    Wenn die Hardware Geräte erkennen kann, die mit dem Aux -Port verbunden sind, sollte die Hardware das MediaItem als PLAYABLE markieren, wenn die Eingabe angeschlossen ist. Die Hardware sollte immer noch aufgezählt (aber nicht PLAYABLE ), wenn nichts mit diesem Port verbunden war. Wenn die Hardware keine solche Funktion hat, muss das MediaItem immer auf PLAYABLE eingestellt sein.

    Zusätzliche Felder

    Definieren Sie die folgenden Felder:

    • 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"

    Der Client muss die Medien der obersten Ebene für Elemente mit dem zusätzlichen Feld Set EXTRA_CD_DISK oder EXTRA_AUX_PORT_NAME überprüfen.

    Detaillierte Beispiele

    Die folgenden Beispiele befassen sich mit der MediaBrowser -Baumstruktur für Quellentypen, die Teil dieses Designs sind.

    Broadcast Radio MediaBrowserService (Handle ACTION_PLAY_BROADCASTRADIO ):

    • Stationen (durchbr EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS durch
      • BBC One (spielbar) URI: broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
      • ABC 88.1 (spielbar) URI: broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
      • ABC 88.1 HD1 (spielbar) URI: broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
      • ABC 88.1 HD2 (spielbar) URI: broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
      • 90,5 FM (spielbar) - FM ohne RDSURI: broadcastradio://program/AMFM_FREQUENCY/90500
      • 620 Uhr (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/620
      • BBC One (spielbar) URI: broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
    • Favoriten (browsable, spielbar) EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES
      • BBC One (spielbar) URI: broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
      • BBC Two (nicht spielbar) URI: broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
    • AM (Browsable, Playable): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
      • 530 Uhr (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/530
      • 540 Uhr (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/540
      • 550 Uhr (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/550
    • Fm (browsable, spielbar): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
      • 87.7 FM (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/87700
      • 87.9 FM (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/87900
      • 88.1 FM (spielbar) URI: broadcastradio://program/AMFM_FREQUENCY/88100
    • DAB (spielbar): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"

    Audio CD MediaBrowserService (Handle ACTION_PLAY_AUDIOCD ):

    • Disc 1 (spielbar) EXTRA_CD_DISK=1
    • Disc 2 (Browsable, spielbar) EXTRA_CD_DISK=2
      • Track 1 (spielbar) EXTRA_CD_TRACK=1
      • Track 2 (spielbar) EXTRA_CD_TRACK=2
    • Meine Musik -CD (Browsable, spielbar) EXTRA_CD_DISK=3
      • Allein alleine (spielbar) EXTRA_CD_TRACK=1
      • Reise, Reise (spielbar) EXTRA_CD_TRACK=2
    • Leerer Steckplatz 4 (nicht spielbar) EXTRA_CD_DISK=4

    Aux MediaBrowserService (Handle ACTION_PLAY_AUX ):

    • Aux Front (spielbar) EXTRA_AUX_PORT_NAME="front"
    • Aux hinten (spielbar) EXTRA_AUX_PORT_NAME="rear"