Mit Android Auto und Android Automotive OS können Sie Nutzern Ihre Medien-App-Inhalte in ihrem Auto zur Verfügung stellen.
Es gibt zwei Möglichkeiten, Medien-Apps für Autos zu erstellen:
In diesem Leitfaden wird beschrieben, wie Sie mit einem
MediaBrowserService
und einemMediaSession
eine App erstellen, mit der Android Auto und Android Automotive OS eine Verbindung herstellen können, um für die Verwendung im Auto optimierte Ansichten für das Durchsuchen und Abspielen von Medien zu rendern.Medien-Apps können auch mit Car App Library-Vorlagen erstellt werden, die anpassbare Formatierung, Browsing-Funktionen und erweiterte benutzerdefinierte Aktionen bieten. Weitere Informationen zur Implementierung finden Sie unter Medien-App mit Vorlagen erstellen. Vorlagenbasierte Media-Apps werden derzeit nur auf Android Auto unterstützt.
In dieser Anleitung werden die erforderlichen Komponenten eines MediaBrowserService
und MediaSession
beschrieben, die Ihre App benötigt, um auf Android Auto oder Android Automotive OS zu funktionieren. Nachdem Sie die Medieninfrastruktur abgeschlossen haben, können Sie Ihrer Medien-App Unterstützung für Android Auto und Unterstützung für Android Automotive OS hinzufügen.
In diesem Leitfaden wird davon ausgegangen, dass Sie bereits eine Media-App haben, die Audio auf einem Smartphone abspielt, und dass Ihre Media-App der Architektur für Android-Media-Apps entspricht.
Hinweis
- Dokumentation zu Android Media APIs
- Designrichtlinien für Media-Apps
- Sehen Sie sich die in diesem Abschnitt aufgeführten wichtigen Begriffe und Konzepte an.
Wichtige Begriffe und Konzepte
- Medienbrowser-Dienst
- Ein Android-Dienst, der von deiner Media-App implementiert wird und der
MediaBrowserServiceCompat
-API entspricht. Ihre App verwendet diesen Dienst, um ihre Inhalte zu präsentieren. - Media-Browser
- Eine API, die von Media-Apps verwendet wird, um Media-Browser-Dienste zu erkennen und deren Inhalte anzuzeigen. Android Auto und Android Automotive OS verwenden einen Media-Browser, um den Media-Browser-Dienst Ihrer App zu finden.
- Medienelement
Der Media-Browser organisiert seine Inhalte in einer Baumstruktur von
MediaItem
-Objekten. Ein Media-Element kann eines oder beide der folgenden Flags haben:FLAG_PLAYABLE
: Gibt an, dass der Artikel ein Blatt im Inhaltsbaum ist. Das Element stellt einen einzelnen Soundstream dar, z. B. einen Titel auf einem Album, ein Kapitel in einem Hörbuch oder eine Folge eines Podcasts.FLAG_BROWSABLE
: Gibt an, dass das Element ein Knoten im Inhaltsbaum ist und untergeordnete Elemente hat. Das Element stellt beispielsweise ein Album dar und seine untergeordneten Elemente sind die Songs auf dem Album.
Ein Medienelement, das sowohl durchsuchbar als auch abspielbar ist, verhält sich wie eine Playlist. Sie können das Element selbst auswählen, um alle untergeordneten Elemente abzuspielen, oder die untergeordneten Elemente durchsuchen.
- Für Fahrzeuge optimiert
Eine Aktivität für eine Android Automotive OS-App, die den Android Automotive OS-Designrichtlinien entspricht. Die Benutzeroberfläche für diese Aktivitäten wird nicht von Android Automotive OS gerendert. Sie müssen also dafür sorgen, dass Ihre App den Designrichtlinien entspricht. Dazu gehören in der Regel größere Tippziele und Schriftgrößen, Unterstützung für den Tag- und Nachtmodus sowie höhere Kontrastverhältnisse.
Fahrzeugoptimierte Benutzeroberflächen dürfen nur angezeigt werden, wenn keine Car User Experience Restrictions (CUXRs) gelten, da diese Oberflächen möglicherweise eine längere Aufmerksamkeit oder Interaktion des Nutzers erfordern. CUXRs sind nicht wirksam, wenn das Auto steht oder geparkt ist, aber immer, wenn es sich bewegt.
Sie müssen keine Aktivitäten für Android Auto entwerfen, da Android Auto eine eigene für Fahrzeuge optimierte Benutzeroberfläche mit den Informationen aus Ihrem Media-Browser-Dienst erstellt.
Manifestdateien der App konfigurieren
Bevor Sie Ihren Media-Browser-Dienst erstellen können, müssen Sie die Manifestdateien Ihrer App konfigurieren.
Medienbrowser-Dienst deklarieren
Sowohl Android Auto als auch Android Automotive OS stellen über Ihren Media-Browser-Dienst eine Verbindung zu Ihrer App her, um Medieninhalte zu durchsuchen. Deklarieren Sie Ihren MediaBrowser-Dienst in Ihrem Manifest, damit Android Auto und Android Automotive OS den Dienst erkennen und eine Verbindung zu Ihrer App herstellen können.
Das folgende Code-Snippet zeigt, wie Sie Ihren Media-Browser-Dienst in Ihrem Manifest deklarieren. Fügen Sie diesen Code in die Manifestdatei für Ihr Android Automotive OS-Modul und in die Manifestdatei für Ihre Smartphone-App ein.
<application>
...
<service android:name=".MyMediaBrowserService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
...
</application>
App-Symbole angeben
Sie müssen App-Symbole angeben, die von Android Auto und Android Automotive OS verwendet werden können, um Ihre App in der System-UI darzustellen. Es sind zwei Arten von Symbolen erforderlich:
- Launcher-Symbol
- Attributionssymbol
Launcher-Symbol
Das Launcher-Symbol repräsentiert Ihre App in der System-UI, z. B. im Launcher und in der Symbolleiste. Sie können angeben, dass das Symbol Ihrer mobilen App für Ihre Car Media-App verwendet werden soll. Verwenden Sie dazu die folgende Manifestdeklaration:
<application
...
android:icon="@mipmap/ic_launcher"
...
/>
Wenn Sie ein anderes Symbol als das Ihrer mobilen App verwenden möchten, legen Sie die Eigenschaft android:icon
im <service>
-Element Ihres Media-Browser-Dienstes im Manifest fest:
<application>
...
<service
...
android:icon="@mipmap/auto_launcher"
...
/>
</application>
Attributionssymbol

Abbildung 1: Symbol für die Quellenangabe auf der Medienkarte.
Das Attributionssymbol wird an Stellen verwendet, an denen Medieninhalte Vorrang haben, z. B. auf Medienkarten. Sie können das kleine Symbol, das für Benachrichtigungen verwendet wird, wiederverwenden. Dieses Symbol muss einfarbig sein. Sie können ein Symbol angeben, das zur Darstellung Ihrer App verwendet wird, indem Sie die folgende Manifestdeklaration verwenden:
<application>
...
<meta-data
android:name="androidx.car.app.TintableAttributionIcon"
android:resource="@drawable/ic_status_icon" />
...
</application>
Medienbrowser-Dienst erstellen
Sie erstellen einen Medienbrowser-Dienst, indem Sie die Klasse MediaBrowserServiceCompat
erweitern. Sowohl Android Auto als auch Android Automotive OS können Ihren Dienst dann für Folgendes verwenden:
- Durchsuchen Sie die Inhaltshierarchie Ihrer App, um dem Nutzer ein Menü zu präsentieren.
- Rufen Sie das Token für das
MediaSessionCompat
-Objekt Ihrer App ab, um die Audiowiedergabe zu steuern.
Sie können Ihren Mediabrowserdienst auch verwenden, um anderen Clients den Zugriff auf Medieninhalte aus Ihrer App zu ermöglichen. Diese Media-Clients können andere Apps auf dem Smartphone eines Nutzers oder andere Remote-Clients sein.
Workflow für Medienbrowser-Dienst
In diesem Abschnitt wird beschrieben, wie Android Automotive OS und Android Auto während eines typischen Nutzer-Workflows mit Ihrem Media-Browser-Dienst interagieren.
- Der Nutzer startet Ihre App unter Android Automotive OS oder Android Auto.
- Android Automotive OS oder Android Auto stellen über die Methode
onCreate()
eine Verbindung zum Media Browser-Dienst Ihrer App her. In Ihrer Implementierung der MethodeonCreate()
müssen Sie einMediaSessionCompat
-Objekt und das zugehörige Callback-Objekt erstellen und registrieren. - Android Automotive OS oder Android Auto ruft die Methode
onGetRoot()
Ihres Dienstes auf, um das Stamm-Media-Element in Ihrer Inhaltshierarchie abzurufen. Das Stamm-Media-Element wird nicht angezeigt, sondern zum Abrufen weiterer Inhalte aus Ihrer App verwendet. - Android Automotive OS oder Android Auto ruft die Methode
onLoadChildren()
Ihres Dienstes auf, um die untergeordneten Elemente des Stamm-Media-Elements abzurufen. In Android Automotive OS und Android Auto werden diese Media-Elemente als oberste Ebene der Inhaltselemente angezeigt. Weitere Informationen dazu, was das System auf dieser Ebene erwartet, finden Sie auf dieser Seite im Abschnitt Struktur des Stammmenüs. - Wenn der Nutzer ein durchsuchbares Media-Element auswählt, wird die Methode
onLoadChildren()
Ihres Dienstes noch einmal aufgerufen, um die untergeordneten Elemente des ausgewählten Menüelements abzurufen. - Wenn der Nutzer ein abspielbares Media-Element auswählt, ruft Android Automotive OS oder Android Auto die entsprechende Media-Sitzungs-Callback-Methode auf, um diese Aktion auszuführen.
- Wenn Ihre App dies unterstützt, kann der Nutzer auch in Ihren Inhalten suchen. In diesem Fall rufen Android Automotive OS oder Android Auto die Methode
onSearch()
Ihres Dienstes auf.
Contenthierarchie erstellen
Android Auto und Android Automotive OS rufen den MediaBrowser-Dienst Ihrer App auf, um herauszufinden, welche Inhalte verfügbar sind. Dazu müssen Sie in Ihrem Media-Browser-Dienst zwei Methoden implementieren: onGetRoot()
und onLoadChildren()
.
„onGetRoot“ implementieren
Die Methode onGetRoot()
Ihres Dienstes gibt Informationen zum Stammknoten Ihrer Inhaltshierarchie zurück.
Android Auto und Android Automotive OS verwenden diesen Stammknoten, um den Rest Ihrer Inhalte mit der Methode onLoadChildren()
anzufordern.
Das folgende Code-Snippet zeigt eine einfache Implementierung der Methode onGetRoot()
:
Kotlin
override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? = // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. null } else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
Java
@Override public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) { // Verify that the specified package is allowed to access your // content. You'll need to write your own logic to do this. if (!isValid(clientPackageName, clientUid)) { // If the request comes from an untrusted package, return null. // No further calls will be made to other media browsing methods. return null; } return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null); }
Ein detaillierteres Beispiel für diese Methode finden Sie in der onGetRoot()
-Methode in der Universal Android Music Player-Beispiel-App auf GitHub.
Paketvalidierung für onGetRoot() hinzufügen
Wenn die onGetRoot()
-Methode Ihres Dienstes aufgerufen wird, übergibt das aufrufende Paket Identifikationsinformationen an Ihren Dienst. Ihr Dienst kann anhand dieser Informationen entscheiden, ob das Paket auf Ihre Inhalte zugreifen darf. Sie können beispielsweise den Zugriff auf die Inhalte Ihrer App auf eine Liste genehmigter Pakete beschränken, indem Sie den clientPackageName
mit Ihrer Zulassungsliste vergleichen und das Zertifikat überprüfen, das zum Signieren des APK des Pakets verwendet wurde. Wenn das Paket nicht überprüft werden kann, gib null
zurück, um den Zugriff auf deine Inhalte zu verweigern.
Damit System-Apps wie Android Auto und Android Automotive OS auf Ihre Inhalte zugreifen können, muss Ihr Dienst immer einen Wert ungleich null für BrowserRoot
zurückgeben, wenn diese System-Apps die Methode onGetRoot()
aufrufen. Die Signatur der Android Automotive OS-System-App kann je nach Marke und Modell des Autos variieren. Daher müssen Sie Verbindungen von allen System-Apps zulassen, um Android Automotive OS zuverlässig zu unterstützen.
Das folgende Code-Snippet zeigt, wie Ihr Dienst prüfen kann, ob das aufrufende Paket eine System-App ist:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
Dieses Code-Snippet ist ein Auszug aus der Klasse PackageValidator
in der Universal Android Music Player-Beispiel-App auf GitHub. In dieser Klasse finden Sie ein detaillierteres Beispiel für die Implementierung der Paketvalidierung für die onGetRoot()
-Methode Ihres Dienstes.
Sie müssen nicht nur System-Apps zulassen, sondern auch Google Assistant die Verbindung zu Ihrem MediaBrowserService
erlauben. Google Assistant hat separate Paketnamen für das Smartphone, das Android Auto enthält, und für Android Automotive OS.
onLoadChildren() implementieren
Nachdem Android Auto und Android Automotive OS das Stammknotenobjekt erhalten haben, wird ein Menü der obersten Ebene erstellt, indem onLoadChildren()
für das Stammknotenobjekt aufgerufen wird, um die untergeordneten Elemente abzurufen. Client-Apps erstellen Untermenüs, indem sie dieselbe Methode mit untergeordneten Knotenobjekten aufrufen.
Jeder Knoten in Ihrer Inhaltshierarchie wird durch ein MediaBrowserCompat.MediaItem
-Objekt dargestellt. Jedes dieser Media-Elemente wird durch einen eindeutigen ID-String identifiziert. Client-Apps behandeln diese ID-Strings als intransparente Tokens. Wenn eine Clientanwendung ein Untermenü aufrufen oder ein Media-Element abspielen möchte, übergibt sie das Token. Ihre App ist dafür verantwortlich, das Token dem entsprechenden Media-Element zuzuordnen.
Das folgende Code-Snippet zeigt eine einfache Implementierung der Methode onLoadChildren()
:
Kotlin
override fun onLoadChildren( parentMediaId: String, result: Result<List<MediaBrowserCompat.MediaItem>> ) { // Assume for example that the music catalog is already loaded/cached. val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf() // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID == parentMediaId) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems) }
Java
@Override public void onLoadChildren(final String parentMediaId, final Result<List<MediaBrowserCompat.MediaItem>> result) { // Assume for example that the music catalog is already loaded/cached. List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); // Check whether this is the root menu: if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) { // Build the MediaItem objects for the top level // and put them in the mediaItems list. } else { // Examine the passed parentMediaId to see which submenu we're at // and put the children of that menu in the mediaItems list. } result.sendResult(mediaItems); }
Ein vollständiges Beispiel für diese Methode finden Sie in der Beispiel-App „Universal Android Music Player“ auf GitHub in der Methode onLoadChildren()
.
Strukturieren des Stammmenüs

Abbildung 2: Root-Inhalte, die als Navigationstabs angezeigt werden.
Für Android Auto und Android Automotive OS gelten bestimmte Einschränkungen hinsichtlich der Struktur des Stammmenüs. Diese werden über Root-Hinweise an MediaBrowserService
übermittelt, die über das Argument Bundle
gelesen werden können, das an onGetRoot()
übergeben wird.
Wenn Sie diese Hinweise beachten, kann das System die Root-Inhalte optimal als Navigationstabs darstellen. Wenn Sie diese Hinweise nicht beachten, werden einige Root-Inhalte möglicherweise vom System entfernt oder weniger auffindbar gemacht. Es werden zwei Hinweise gesendet:
- Limit für die Anzahl der untergeordneten Elemente der obersten Ebene: In den meisten Fällen können Sie davon ausgehen, dass diese Zahl vier ist. Das bedeutet, dass nicht mehr als vier Tabs angezeigt werden können.
- Unterstützte Flags für die untergeordneten Elemente des Root-Elements: Dieser Wert ist in der Regel
MediaItem#FLAG_BROWSABLE
. Das bedeutet, dass nur durchsuchbare Elemente, nicht aber abspielbare Elemente als Tabs angezeigt werden können.
Verwenden Sie den folgenden Code, um die relevanten Root-Hinweise zu lesen:
Kotlin
import androidx.media.utils.MediaConstants // Later, in your MediaBrowserServiceCompat. override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle ): BrowserRoot { val maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4) val supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE) // Rest of method... }
Java
import androidx.media.utils.MediaConstants; // Later, in your MediaBrowserServiceCompat. @Override public BrowserRoot onGetRoot( String clientPackageName, int clientUid, Bundle rootHints) { int maximumRootChildLimit = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT, /* defaultValue= */ 4); int supportedRootChildFlags = rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS, /* defaultValue= */ MediaItem.FLAG_BROWSABLE); // Rest of method... }
Sie können die Logik für die Struktur Ihrer Inhaltshierarchie basierend auf den Werten dieser Hinweise verzweigen, insbesondere wenn sich Ihre Hierarchie zwischen MediaBrowser
-Integrationen außerhalb von Android Auto und Android Automotive OS unterscheidet.
Wenn Sie beispielsweise normalerweise ein abspielbares Stamm-Element präsentieren, möchten Sie es möglicherweise aufgrund des Hinweises zum Wert der unterstützten Flags stattdessen unter einem durchsuchbaren Stamm-Element einbetten.
Neben den Root-Hinweisen gibt es einige zusätzliche Richtlinien, die Sie beachten sollten, damit Tabs optimal gerendert werden:
- Stellen Sie für jedes Tab-Element einfarbige, vorzugsweise weiße Symbole bereit.
- Geben Sie für jedes Tab-Element kurze, aber aussagekräftige Labels an. Wenn Sie Labels kurz halten, verringern Sie die Wahrscheinlichkeit, dass die Strings abgeschnitten werden.
Media-Grafiken anzeigen
Das Artwork für Media-Elemente muss als lokaler URI über ContentResolver.SCHEME_CONTENT
oder ContentResolver.SCHEME_ANDROID_RESOURCE
übergeben werden.
Dieser lokale URI muss entweder zu einer Bitmap oder einem Vektordrawable in den Ressourcen der Anwendung aufgelöst werden. Für MediaDescriptionCompat
-Objekte, die Elemente in der Inhaltshierarchie darstellen, übergeben Sie den URI über setIconUri()
.
Für MediaMetadataCompat
-Objekte, die das aktuell wiedergegebene Element darstellen, übergeben Sie den URI über putString()
mit einem der folgenden Schlüssel:
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI
MediaMetadataCompat.METADATA_KEY_ART_URI
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI
In den folgenden Schritten wird beschrieben, wie Sie Grafiken von einem Web-URI herunterladen und über einen lokalen URI verfügbar machen. Ein vollständigeres Beispiel finden Sie in der Implementierung von openFile()
und den umgebenden Methoden in der Universal Android Music Player-Beispiel-App.
Erstellen Sie einen
content://
-URI, der dem Web-URI entspricht. Der Media Browser-Dienst und die Media Session übergeben diesen Inhalts-URI an Android Auto und Android Automotive OS.Kotlin
fun Uri.asAlbumArtContentURI(): Uri { return Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(this.getPath()) // Make sure you trust the URI .build() }
Java
public static Uri asAlbumArtContentURI(Uri webUri) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_CONTENT) .authority(CONTENT_PROVIDER_AUTHORITY) .appendPath(webUri.getPath()) // Make sure you trust the URI! .build(); }
Prüfen Sie in Ihrer Implementierung von
ContentProvider.openFile()
, ob eine Datei für den entsprechenden URI vorhanden ist. Falls nicht, laden Sie die Bilddatei herunter und speichern Sie sie im Cache. Im folgenden Code-Snippet wird Glide verwendet.Kotlin
override fun openFile(uri: Uri, mode: String): ParcelFileDescriptor? { val context = this.context ?: return null val file = File(context.cacheDir, uri.path) if (!file.exists()) { val remoteUri = Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.path) .build() val cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS) cacheFile.renameTo(file) file = cacheFile } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) }
Java
@Nullable @Override public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { Context context = this.getContext(); File file = new File(context.getCacheDir(), uri.getPath()); if (!file.exists()) { Uri remoteUri = new Uri.Builder() .scheme("https") .authority("my-image-site") .appendPath(uri.getPath()) .build(); File cacheFile = Glide.with(context) .asFile() .load(remoteUri) .submit() .get(DOWNLOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS); cacheFile.renameTo(file); file = cacheFile; } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }
Weitere Informationen zu Inhaltsanbietern finden Sie unter Inhaltsanbieter erstellen.
Inhaltsstile anwenden
Nachdem Sie Ihre Inhaltshierarchie mit durchsuchbaren oder abspielbaren Elementen erstellt haben, können Sie Inhaltsstile anwenden, die bestimmen, wie diese Elemente im Auto angezeigt werden.
Sie können die folgenden Inhaltsstile verwenden:
- Listenelemente
-
Bei diesem Content-Stil werden Titel und Metadaten gegenüber Bildern priorisiert.
- Rasterelemente
-
Bei diesem Content-Stil werden Bilder gegenüber Titeln und Metadaten priorisiert.
Standardstile für Inhalte festlegen
Sie können globale Standardeinstellungen für die Darstellung Ihrer Media-Elemente festlegen, indem Sie bestimmte Konstanten in das BrowserRoot
-Extras-Bundle der onGetRoot()
-Methode Ihres Dienstes einfügen. Android Auto und Android Automotive OS lesen dieses Bundle und suchen nach diesen Konstanten, um den entsprechenden Stil zu bestimmen.
Die folgenden Extras können als Schlüssel im Bundle verwendet werden:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
: Gibt einen Präsentationshinweis für alle durchsuchbaren Elemente im Browsing-Baum an.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
: Gibt einen Präsentationshinweis für alle abspielbaren Elemente im Browsing-Baum an.
Die Schlüssel können den folgenden ganzzahligen Konstantenwerten zugeordnet werden, um die Darstellung der Elemente zu beeinflussen:
DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM
: Die entsprechenden Elemente werden als Listenelemente dargestellt.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM
: Die entsprechenden Elemente werden als Rasterelemente dargestellt.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM
: Die entsprechenden Elemente werden als Listenelemente vom Typ „category“ dargestellt. Diese sind mit normalen Listenelementen identisch, mit der Ausnahme, dass um die Symbole der Elemente herum Ränder eingefügt werden, da die Symbole in klein besser aussehen. Die Symbole müssen färbbare Vektor-Drawables sein. Dieser Hinweis sollte nur für durchsuchbare Elemente angezeigt werden.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM
: Die entsprechenden Elemente werden als Rasterelemente der Kategorie dargestellt. Diese sind mit normalen Rasterelementen identisch, mit dem Unterschied, dass um die Symbole der Elemente herum Ränder angewendet werden, da die Symbole in klein besser aussehen. Die Symbole müssen färbbare Vektor-Drawables sein. Dieser Hinweis sollte nur für durchsuchbare Elemente angezeigt werden.
Im folgenden Code-Snippet wird gezeigt, wie Sie das Standardinhaltsformat für durchsuchbare Elemente auf Raster und für abspielbare Elemente auf Listen festlegen:
Kotlin
import androidx.media.utils.MediaConstants @Nullable override fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); return new BrowserRoot(ROOT_ID, extras); }
Inhaltsstile für einzelne Elemente festlegen
Mit der Content Style API können Sie den Standardinhaltsstil für untergeordnete Elemente eines durchsuchbaren Media-Elements sowie für Media-Elemente selbst überschreiben.
Wenn Sie die Standardeinstellung für die children eines durchsuchbaren Media-Elements überschreiben möchten, erstellen Sie im MediaDescription
des Media-Elements ein Extras-Bundle und fügen Sie die oben genannten Hinweise hinzu. DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
gilt für die abspielbaren untergeordneten Elemente dieses Elements, während DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
für die durchsuchbaren untergeordneten Elemente dieses Elements gilt.
Wenn Sie den Standardwert für ein bestimmtes Media-Element selbst und nicht für seine untergeordneten Elemente überschreiben möchten, erstellen Sie im MediaDescription
des Media-Elements ein Extras-Bundle und fügen Sie einen Hinweis mit dem Schlüssel DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM
hinzu.
Verwenden Sie dieselben Werte wie oben beschrieben, um die Darstellung des Artikels festzulegen.
Das folgende Code-Snippet zeigt, wie Sie ein durchsuchbares MediaItem
erstellen, das den Standardinhaltsstil für sich selbst und seine untergeordneten Elemente überschreibt. Es wird als Kategorie-Listenelement formatiert, seine durchsuchbaren untergeordneten Elemente als Listenelemente und seine abspielbaren untergeordneten Elemente als Gridelemente:
Kotlin
import androidx.media.utils.MediaConstants private fun createBrowsableMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM) mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createBrowsableMediaItem( String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE, MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE); }
Elemente anhand von Titelhinweisen gruppieren
Um ähnliche Media-Elemente zu gruppieren, verwenden Sie einen Hinweis pro Element. Für jedes Media-Element in einer Gruppe muss im MediaDescription
ein Extras-Bundle deklariert werden, das eine Zuordnung mit dem Schlüssel DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
und einem identischen Stringwert enthält. Lokalisieren Sie diesen String, der als Titel der Gruppe verwendet wird.
Das folgende Code-Snippet zeigt, wie Sie ein MediaItem
-Objekt mit der Untergruppenüberschrift "Songs"
erstellen:
Kotlin
import androidx.media.utils.MediaConstants private fun createMediaItem( mediaId: String, folderName: String, iconUri: Uri ): MediaBrowser.MediaItem { val mediaDescriptionBuilder = MediaDescription.Builder() mediaDescriptionBuilder.setMediaId(mediaId) mediaDescriptionBuilder.setTitle(folderName) mediaDescriptionBuilder.setIconUri(iconUri) val extras = Bundle() extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") mediaDescriptionBuilder.setExtras(extras) return MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/) }
Java
import androidx.media.utils.MediaConstants; private MediaBrowser.MediaItem createMediaItem(String mediaId, String folderName, Uri iconUri) { MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder(); mediaDescriptionBuilder.setMediaId(mediaId); mediaDescriptionBuilder.setTitle(folderName); mediaDescriptionBuilder.setIconUri(iconUri); Bundle extras = new Bundle(); extras.putString( MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs"); mediaDescriptionBuilder.setExtras(extras); return new MediaBrowser.MediaItem( mediaDescriptionBuilder.build(), /* playable or browsable flag*/); }
Ihre App muss alle Media-Elemente, die Sie gruppieren möchten, als zusammenhängenden Block übergeben. Angenommen, Sie möchten zwei Gruppen von Media-Elementen, „Songs“ und „Alben“, in dieser Reihenfolge anzeigen und Ihre App übergibt fünf Media-Elemente in der folgenden Reihenfolge:
- Medienelement A mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Medienelement B mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- Medienelement C mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Mediendatei D mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Medienelement E mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
Da die Media-Elemente für die Gruppen „Songs“ und „Alben“ nicht in zusammenhängenden Blöcken gespeichert werden, interpretiert Android Auto und Android Automotive OS dies als die folgenden vier Gruppen:
- Gruppe 1 mit dem Namen „Songs“ mit Media-Element A
- Gruppe 2 mit dem Namen „Alben“, die das Media-Element B enthält
- Gruppe 3 mit dem Namen „Songs“ mit den Media-Elementen C und D
- Gruppe 4 mit dem Namen „Alben“, die das Media-Element E enthält
Damit diese Elemente in zwei Gruppen angezeigt werden, muss Ihre App die Media-Elemente stattdessen in der folgenden Reihenfolge übergeben:
- Medienelement A mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Medienelement C mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Mediendatei D mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
- Medienelement B mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
- Medienelement E mit
extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
Zusätzliche Metadatenindikatoren anzeigen
Sie können zusätzliche Metadatenindikatoren einfügen, um auf einen Blick Informationen zu Inhalten in der Media-Browser-Baumstruktur und während der Wiedergabe zu erhalten. Im Browse-Baum werden in Android Auto und Android Automotive OS die Extras gelesen, die einem Element zugeordnet sind. Es wird nach bestimmten Konstanten gesucht, um zu ermitteln, welche Indikatoren angezeigt werden sollen. Während der Medienwiedergabe lesen Android Auto und Android Automotive OS die Metadaten für die Mediensitzung und suchen nach bestimmten Konstanten, um anzuzeigende Indikatoren zu ermitteln.

Abbildung 3: Wiedergabeansicht mit Metadaten, die den Song und den Künstler identifizieren, sowie einem Symbol für explizite Inhalte.

Abbildung 4: Die Browsing-Ansicht mit einem Punkt für nicht wiedergegebene Inhalte beim ersten Element und einem Fortschrittsbalken für teilweise wiedergegebene Inhalte beim zweiten Element.
Die folgenden Konstanten können sowohl in MediaItem
-Beschreibungsextras als auch in MediaMetadata
-Extras verwendet werden:
EXTRA_DOWNLOAD_STATUS
: Gibt den Downloadstatus eines Elements an. Verwenden Sie diese Konstante als Schlüssel. Die folgenden langen Konstanten sind die möglichen Werte:STATUS_DOWNLOADED
: Der Artikel wurde vollständig heruntergeladen.STATUS_DOWNLOADING
: Das Element wird heruntergeladen.STATUS_NOT_DOWNLOADED
: Das Element wird nicht heruntergeladen.
METADATA_KEY_IS_EXPLICIT
: Gibt an, ob das Element explizite Inhalte enthält. Wenn Sie angeben möchten, dass ein Artikel explizit ist, verwenden Sie diese Konstante als Schlüssel und den langenMETADATA_VALUE_ATTRIBUTE_PRESENT
als Wert.
Die folgenden Konstanten können nur in MediaItem
-Beschreibungsextras verwendet werden:
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
: Gibt den Abschlussstatus von Langformatinhalten wie Podcastfolgen oder Hörbüchern an. Verwenden Sie diese Konstante als Schlüssel. Die folgenden Integer-Konstanten sind die möglichen Werte:DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED
: Der Artikel wurde noch nicht wiedergegeben.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED
: Der Artikel wurde teilweise wiedergegeben und die aktuelle Position liegt irgendwo in der Mitte.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED
: Der Artikel wurde fertiggestellt.
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
: Gibt den Fortschritt bei der Vervollständigung von Langformatinhalten als Double zwischen 0,0 und 1,0 an. Dieses Extra enthält weitere Informationen zum StatusPARTIALLY_PLAYING
, damit in Android Auto oder Android Automotive OS ein aussagekräftigerer Fortschrittsindikator wie z. B. eine Fortschrittsanzeige angezeigt wird. Wenn Sie dieses Extra verwenden, finden Sie in diesem Leitfaden im Abschnitt Fortschrittsanzeige in der Ansicht „Durchsuchen“ während der Wiedergabe von Inhalten aktualisieren Informationen dazu, wie Sie diesen Indikator nach der ersten Impression auf dem neuesten Stand halten.
Wenn Sie Indikatoren anzeigen möchten, die eingeblendet werden, während der Nutzer den Media-Browser-Baum durchsucht, erstellen Sie ein Extras-Bundle, das eine oder mehrere dieser Konstanten enthält, und übergeben Sie dieses Bundle an die Methode MediaDescription.Builder.setExtras()
.
Das folgende Code-Snippet zeigt, wie Indikatoren für ein explizites Media-Element angezeigt werden, das zu 70% abgeschlossen ist:
Kotlin
import androidx.media.utils.MediaConstants val extras = Bundle() extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED) extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7) val description = MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build() return MediaBrowserCompat.MediaItem(description, /* flags */)
Java
import androidx.media.utils.MediaConstants; Bundle extras = new Bundle(); extras.putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); extras.putInt( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS, MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED); extras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(/*...*/) .setTitle(resources.getString(/*...*/)) .setExtras(extras) .build(); return new MediaBrowserCompat.MediaItem(description, /* flags */);
Wenn Sie Indikatoren für ein Media-Element anzeigen möchten, das gerade wiedergegeben wird, können Sie Long
-Werte für METADATA_KEY_IS_EXPLICIT
oder EXTRA_DOWNLOAD_STATUS
im MediaMetadataCompat
Ihres mediaSession
deklarieren. Die Symbole DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
und DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
können in der Wiedergabeansicht nicht angezeigt werden.
Das folgende Code-Snippet zeigt, wie Sie angeben, dass der aktuelle Song in der Wiedergabeansicht explizit und heruntergeladen ist:
Kotlin
import androidx.media.utils.MediaConstants mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build())
Java
import androidx.media.utils.MediaConstants; mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name") .putString( MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name") .putString( MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI, albumArtUri.toString()) .putLong( MediaConstants.METADATA_KEY_IS_EXPLICIT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) .putLong( MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS, MediaDescriptionCompat.STATUS_DOWNLOADED) .build());
Aktualisieren der Fortschrittsanzeige in der Ansicht „Entdecken“ während der Wiedergabe von Inhalten
Wie bereits erwähnt, können Sie mit dem Extra DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
eine Fortschrittsanzeige für teilweise wiedergegebene Inhalte in der Ansicht „Durchsuchen“ einblenden. Wenn ein Nutzer die teilweise wiedergegebenen Inhalte jedoch über Android Auto oder Android Automotive OS weiter abspielt, wird die Anzeige mit der Zeit ungenau.
Damit die Fortschrittsanzeige in Android Auto und Android Automotive OS auf dem neuesten Stand bleibt, kannst du in MediaMetadataCompat
und PlaybackStateCompat
zusätzliche Informationen angeben, um laufende Inhalte mit Media-Elementen in der Ansicht „Durchsuchen“ zu verknüpfen. Damit für ein Media-Element automatisch eine Fortschrittsanzeige aktualisiert wird, müssen die folgenden Anforderungen erfüllt sein:
- Beim Erstellen muss die
MediaItem
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
in ihren Extras mit einem Wert zwischen 0, 0 und 1, 0 (einschließlich) senden. - Die
MediaMetadataCompat
mussMETADATA_KEY_MEDIA_ID
mit einem Stringwert senden, der der Media-ID entspricht, die an dieMediaItem
übergeben wurde. - Der
PlaybackStateCompat
muss ein Extra mit dem SchlüsselPLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID
enthalten, der einem Stringwert entspricht, der mit der Media-ID übereinstimmt, die anMediaItem
übergeben wird.
Das folgende Code-Snippet zeigt, wie Sie angeben, dass das aktuell wiedergegebene Element mit einem Element in der Ansicht „Durchsuchen“ verknüpft ist:
Kotlin
import androidx.media.utils.MediaConstants // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. val mediaItemExtras = Bundle() mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25) val description = MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build() return MediaBrowserCompat.MediaItem(description, /* flags */) // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()) val playbackStateExtras = Bundle() playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id") mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build())
Java
import androidx.media.utils.MediaConstants; // When the MediaItem is constructed to show in the browse view. // Suppose the item was 25% complete when the user launched the browse view. Bundle mediaItemExtras = new Bundle(); mediaItemExtras.putDouble( MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25); MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId("my-media-id") .setExtras(mediaItemExtras) // ...and any other setters. .build(); return MediaBrowserCompat.MediaItem(description, /* flags */); // Elsewhere, when the user has selected MediaItem for playback. mediaSession.setMetadata( new MediaMetadataCompat.Builder() .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id") // ...and any other setters. .build()); Bundle playbackStateExtras = new Bundle(); playbackStateExtras.putString( MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id"); mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setExtras(playbackStateExtras) // ...and any other setters. .build());
Durchsuchbare Suchergebnisse anzeigen

Abbildung 5: Wiedergabeansicht mit der Option „Suchergebnisse“ zum Aufrufen von Media-Elementen, die mit der Sprachsuche des Nutzers zusammenhängen.
Ihre App kann kontextbezogene Suchergebnisse liefern, die Nutzern angezeigt werden, wenn sie eine Suchanfrage starten. In Android Auto und Android Automotive OS werden diese Ergebnisse über Suchanfrageoberflächen oder über Affordances angezeigt, die auf Anfragen basieren, die zu einem früheren Zeitpunkt in der Sitzung gestellt wurden. Weitere Informationen finden Sie in diesem Leitfaden im Abschnitt Sprachaktionen unterstützen.
Wenn Sie durchsuchbare Suchergebnisse anzeigen möchten, fügen Sie den Konstantenschlüssel BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED
in das Extras-Bundle der Methode onGetRoot()
Ihres Dienstes ein und ordnen Sie ihn dem booleschen Wert true
zu.
Das folgende Code-Snippet zeigt, wie Sie die Unterstützung in der Methode onGetRoot()
aktivieren:
Kotlin
import androidx.media.utils.MediaConstants @Nullable fun onGetRoot( @NonNull clientPackageName: String, clientUid: Int, @Nullable rootHints: Bundle ): BrowserRoot { val extras = Bundle() extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true) return BrowserRoot(ROOT_ID, extras) }
Java
import androidx.media.utils.MediaConstants; @Nullable @Override public BrowserRoot onGetRoot( @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) { Bundle extras = new Bundle(); extras.putBoolean( MediaConstants.BROWSER_SERVICE_EXTRAS_KEY_SEARCH_SUPPORTED, true); return new BrowserRoot(ROOT_ID, extras); }
Überschreiben Sie die Methode onSearch()
in Ihrem Media-Browser-Dienst, um Suchergebnisse zu liefern. Android Auto und Android Automotive OS leiten die Suchbegriffe des Nutzers an diese Methode weiter, wenn ein Nutzer eine Suchanfrageoberfläche oder eine Schaltfläche für Suchergebnisse aufruft.
Sie können die Suchergebnisse der onSearch()
-Methode Ihres Dienstes mit Titelelementen organisieren, um sie übersichtlicher zu gestalten. Wenn Ihre App beispielsweise Musik abspielt, können Sie die Suchergebnisse nach Album, Künstler und Songs sortieren.
Das folgende Code-Snippet zeigt eine einfache Implementierung der Methode onSearch()
:
Kotlin
fun onSearch(query: String, extras: Bundle) { // Detach from results to unblock the caller (if a search is expensive). result.detach() object:AsyncTask() { internal var searchResponse:ArrayList internal var succeeded = false protected fun doInBackground(vararg params:Void):Void { searchResponse = ArrayList() if (doSearch(query, extras, searchResponse)) { succeeded = true } return null } protected fun onPostExecute(param:Void) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse) } else { // This invokes onError() on the search callback. result.sendResult(null) } return null } }.execute() } // Populates resultsToFill with search results. Returns true on success or false on error. private fun doSearch( query: String, extras: Bundle, resultsToFill: ArrayList ): Boolean { // Implement this method. }
Java
@Override public void onSearch(final String query, final Bundle extras, Result<List<MediaItem>> result) { // Detach from results to unblock the caller (if a search is expensive). result.detach(); new AsyncTask<Void, Void, Void>() { List<MediaItem> searchResponse; boolean succeeded = false; @Override protected Void doInBackground(Void... params) { searchResponse = new ArrayList<MediaItem>(); if (doSearch(query, extras, searchResponse)) { succeeded = true; } return null; } @Override protected void onPostExecute(Void param) { if (succeeded) { // Sending an empty List informs the caller that there were no results. result.sendResult(searchResponse); } else { // This invokes onError() on the search callback. result.sendResult(null); } } }.execute() } /** Populates resultsToFill with search results. Returns true on success or false on error. */ private boolean doSearch(String query, Bundle extras, ArrayList<MediaItem> resultsToFill) { // Implement this method. }
Benutzerdefinierte Browse-Aktionen

Abbildung 6 Einzelne benutzerdefinierte Browseraktion
Mit benutzerdefinierten Browse-Aktionen können Sie den MediaItem
-Objekten Ihrer App in der Media-App des Autos benutzerdefinierte Symbole und Labels hinzufügen und Nutzerinteraktionen mit diesen Aktionen verarbeiten. So können Sie die Funktionalität der Media App auf verschiedene Arten erweitern, z. B. durch Hinzufügen der Aktionen „Herunterladen“, „Zur Warteschlange hinzufügen“, „Radiosender abspielen“, „Favorisieren“ oder „Entfernen“.

Abbildung 7. Dreipunkt-Menü für benutzerdefinierte Browse-Aktion
Wenn mehr benutzerdefinierte Aktionen vorhanden sind, als der OEM anzeigen darf, wird dem Nutzer ein Überlaufmenü angezeigt.
So funktioniert es:
Jede benutzerdefinierte Suchaktion wird durch Folgendes definiert:
- Eine Aktions-ID (eine eindeutige String-Kennung)
- Ein Aktionslabel (der Text, der dem Nutzer angezeigt wird)
- Ein URI für ein Aktionssymbol (ein Vektor-Drawable, das eingefärbt werden kann)
Sie definieren eine Liste benutzerdefinierter Browseraktionen global als Teil von BrowseRoot
. Anschließend können Sie eine Teilmenge dieser Aktionen an einzelne MediaItem.
anhängen.
Wenn ein Nutzer mit einer benutzerdefinierten Browsing-Aktion interagiert, erhält Ihre App einen Callback in onCustomAction()
. Anschließend können Sie die Aktion ausführen und die Liste der Aktionen für MediaItem
bei Bedarf aktualisieren. Das ist nützlich für zustandsorientierte Aktionen wie „Favorisieren“ und „Herunterladen“. Bei Aktionen, die nicht aktualisiert werden müssen, z. B. „Play Radio“ (Spiele Radio), müssen Sie die Liste der Aktionen nicht aktualisieren.

Abbildung 8. Symbolleiste für benutzerdefinierte Browseraktionen
Sie können einem Browse-Knoten-Root auch benutzerdefinierte Browse-Aktionen anhängen. Diese Aktionen werden in einer sekundären Symbolleiste unter der Hauptsymbolleiste angezeigt.
Benutzerdefinierte Browseraktionen implementieren
So fügen Sie Ihrem Projekt benutzerdefinierte Browse-Aktionen hinzu:
- Überschreiben Sie zwei Methoden in Ihrer
MediaBrowserServiceCompat
-Implementierung: - Aktionslimits zur Laufzeit parsen:
- Rufen Sie in
onGetRoot()
die maximal zulässige Anzahl von Aktionen für jedesMediaItem
mit dem SchlüsselBROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT
imrootHints
Bundle
ab. Ein Limit von 0 gibt an, dass das Feature vom System nicht unterstützt wird.
- Rufen Sie in
- Globale Liste der benutzerdefinierten Browseraktionen erstellen:
- Erstelle für jede Aktion ein
Bundle
-Objekt mit den folgenden Schlüsseln: *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID
: Die Aktions-ID *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL
: Das Aktionslabel *EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI
: Der URI des Aktionssymbols * Füge alleBundle
-Objekte der Aktion in eine Liste ein.
- Erstelle für jede Aktion ein
- Fügen Sie die globale Liste Ihrem
BrowseRoot
hinzu:- Fügen Sie in den
BrowseRoot
-ExtrasBundle
die Liste der Aktionen alsParcelable
Arraylist
mit dem SchlüsselBROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST
hinzu.
- Fügen Sie in den
- Fügen Sie Ihren
MediaItem
-Objekten Aktionen hinzu:- Sie können einzelnen
MediaItem
-Objekten Aktionen hinzufügen, indem Sie die Liste der Aktions-IDs in denMediaDescriptionCompat
-Extras mit dem SchlüsselDESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST
einfügen. Diese Liste muss eine Teilmenge der globalen Liste der Aktionen sein, die Sie in derBrowseRoot
definiert haben.
- Sie können einzelnen
- Aktionen verarbeiten und Fortschritt oder Ergebnisse zurückgeben:
- Verarbeiten Sie die Aktion in
onCustomAction
anhand der Aktions-ID und aller anderen erforderlichen Daten. Sie können die ID desMediaItem
, das die Aktion ausgelöst hat, aus den Extras mit dem SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID
abrufen. - Sie können die Liste der Aktionen für ein
MediaItem
aktualisieren, indem Sie den SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
in das Fortschritts- oder Ergebnis-Bundle einfügen.
- Verarbeiten Sie die Aktion in
Hier sind einige Änderungen, die Sie in Ihrem BrowserServiceCompat
vornehmen können, um mit benutzerdefinierten Browseraktionen zu beginnen.
BrowserServiceCompat überschreiben
Sie müssen die folgenden Methoden in MediaBrowserServiceCompat
überschreiben.
public void onLoadItem(String itemId, @NonNull Result<MediaBrowserCompat.MediaItem> result)
public void onCustomAction(@NonNull String action, Bundle extras, @NonNull Result<Bundle> result)
Limit für Parsing-Vorgänge
Prüfen Sie, wie viele benutzerdefinierte Browseraktionen unterstützt werden.
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { rootHints.getInt( MediaConstants.BROWSER_ROOT_HINTS_KEY_CUSTOM_BROWSER_ACTION_LIMIT, 0) }
Benutzerdefinierte Browse-Aktion erstellen
Jede Aktion muss in einem separaten Bundle
enthalten sein.
- Aktions-ID
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, "<ACTION_ID>")
- Aktionslabel
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, "<ACTION_LABEL>")
- Aktionssymbol-URI
bundle.putString(MediaConstants.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, "<ACTION_ICON_URI>")
Benutzerdefinierte Browseraktionen für Parceable
ArrayList
hinzufügen
Fügen Sie alle benutzerdefinierten Bundle
-Objekte in ein ArrayList
ein.
private ArrayList<Bundle> createCustomActionsList( CustomBrowseAction browseActions) { ArrayList<Bundle> browseActionsBundle = new ArrayList<>(); for (CustomBrowseAction browseAction : browseActions) { Bundle action = new Bundle(); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID, browseAction.mId); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_LABEL, getString(browseAction.mLabelResId)); action.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ICON_URI, browseAction.mIcon); browseActionsBundle.add(action); } return browseActionsBundle; }
Dem Browsing-Stammverzeichnis eine Liste mit benutzerdefinierten Browsing-Aktionen hinzufügen
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) { Bundle browserRootExtras = new Bundle(); browserRootExtras.putParcelableArrayList( BROWSER_SERVICE_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ROOT_LIST, createCustomActionsList())); mRoot = new BrowserRoot(ROOT_ID, browserRootExtras); return mRoot; }
Aktionen zu einem MediaItem
hinzufügen
MediaDescriptionCompat buildDescription (long id, String title, String subtitle, String description, Uri iconUri, Uri mediaUri, ArrayList<String> browseActionIds) { MediaDescriptionCompat.Builder bob = new MediaDescriptionCompat.Builder(); bob.setMediaId(id); bob.setTitle(title); bob.setSubtitle(subtitle); bob.setDescription(description); bob.setIconUri(iconUri); bob.setMediaUri(mediaUri); Bundle extras = new Bundle(); extras.putStringArrayList( DESCRIPTION_EXTRAS_KEY_CUSTOM_BROWSER_ACTION_ID_LIST, browseActionIds); bob.setExtras(extras); return bob.build(); } MediaItem mediaItem = new MediaItem(buildDescription(...), flags);
Build-Ergebnis für onCustomAction
- mediaId aus
Bundle extras
parsen:@Override public void onCustomAction( @NonNull String action, Bundle extras, @NonNull Result<Bundle> result){ String mediaId = extras.getString(MediaConstans.EXTRAS_KEY_CUSTOM_BROWSER_ACTION_MEDIA_ITEM_ID); }
- Bei asynchronen Ergebnissen wird das Ergebnis getrennt.
result.detach()
- Build-Ergebnis-Bundle
- Nachricht an den Nutzer
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE, mContext.getString(stringRes))
- Element aktualisieren(zum Aktualisieren von Aktionen in einem Element)
mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM, mediaId);
- Wiedergabeansicht öffnen
//Shows user the PBV without changing the playback state mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_SHOW_PLAYING_ITEM, null);
- Knoten aktualisieren
//Change current browse node to mediaId mResultBundle.putString(EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_BROWSE_NODE, mediaId);
- Nachricht an den Nutzer
- Bei einem Fehler rufen Sie
result.sendError(resultBundle).
an. - Wenn es ein Fortschritts-Update gibt, rufen Sie
result.sendProgressUpdate(resultBundle)
auf. - Beende den Vorgang, indem du
result.sendResult(resultBundle)
anrufst.
Aktionsstatus aktualisieren
Mit der Methode result.sendProgressUpdate(resultBundle)
und dem Schlüssel EXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
können Sie MediaItem
aktualisieren, um den neuen Status der Aktion widerzuspiegeln. So können Sie dem Nutzer in Echtzeit Feedback zum Fortschritt und Ergebnis seiner Aktion geben.
Beispiel: Download-Aktion
Hier ist ein Beispiel dafür, wie Sie diese Funktion verwenden können, um eine Downloadaktion mit drei Status zu implementieren:
- Herunterladen: Dies ist der Ausgangszustand der Aktion. Wenn der Nutzer diese Aktion auswählt, können Sie sie durch „Wird heruntergeladen“ ersetzen und
sendProgressUpdate
aufrufen, um die Benutzeroberfläche zu aktualisieren. - Wird heruntergeladen: Dieser Status gibt an, dass der Download läuft. Sie können diesen Status verwenden, um dem Nutzer eine Fortschrittsanzeige oder einen anderen Indikator zu präsentieren.
- Heruntergeladen: Dieser Status gibt an, dass der Download abgeschlossen ist. Wenn der Download abgeschlossen ist, können Sie „Downloading“ (Wird heruntergeladen) durch „Downloaded“ (Heruntergeladen) ersetzen und
sendResult
mit dem SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
aufrufen, um anzugeben, dass das Element aktualisiert werden soll. Außerdem können Sie mit dem SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_MESSAGE
eine Erfolgsmeldung für den Nutzer anzeigen.
So können Sie dem Nutzer klares Feedback zum Downloadprozess und seinem aktuellen Status geben. Mit Symbolen können Sie noch mehr Details hinzufügen, um den Downloadstatus von 25%, 50 % und 75% anzuzeigen.
Beispiel: Lieblingsaktion
Ein weiteres Beispiel ist eine Lieblingsaktion mit zwei Status:
- Favorisieren: Diese Aktion wird für Elemente angezeigt, die sich nicht in der Favoritenliste des Nutzers befinden. Wenn der Nutzer diese Aktion auswählt, können Sie sie durch „Favorisiert“ ersetzen und
sendResult
mit dem SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
aufrufen, um die Benutzeroberfläche zu aktualisieren. - Favorisiert: Diese Aktion wird für Elemente angezeigt, die sich in der Favoritenliste des Nutzers befinden. Wenn der Nutzer diese Aktion auswählt, können Sie sie durch „Favorisieren“ ersetzen und
sendResult
mit dem SchlüsselEXTRAS_KEY_CUSTOM_BROWSER_ACTION_RESULT_REFRESH_ITEM
aufrufen, um die Benutzeroberfläche zu aktualisieren.
Dieser Ansatz bietet Nutzern eine klare und konsistente Möglichkeit, ihre Lieblingsartikel zu verwalten.
Diese Beispiele veranschaulichen die Flexibilität benutzerdefinierter Browse-Aktionen und wie Sie damit eine Vielzahl von Funktionen mit Echtzeit-Feedback für eine verbesserte Nutzerfreundlichkeit in der Media-App des Autos implementieren können.
Eine vollständige Beispielimplementierung dieser Funktion finden Sie im Projekt TestMediaApp
.
Wiedergabesteuerung aktivieren
Android Auto und Android Automotive OS senden Befehle zur Wiedergabesteuerung über die MediaSessionCompat
deines Dienstes.
Sie müssen eine Sitzung registrieren und die zugehörigen Callback-Methoden implementieren.
Mediensitzung registrieren
Erstelle in der Methode onCreate()
deines Media-Browser-Dienstes ein MediaSessionCompat
und registriere dann die Media-Session, indem du setSessionToken()
aufrufst.
Das folgende Code-Snippet zeigt, wie eine Mediensitzung erstellt und registriert wird:
Kotlin
override fun onCreate() { super.onCreate() ... // Start a new MediaSession. val session = MediaSessionCompat(this, "session tag").apply { // Set a callback object that implements MediaSession.Callback // to handle play control requests. setCallback(MyMediaSessionCallback()) } sessionToken = session.sessionToken ... }
Java
public void onCreate() { super.onCreate(); ... // Start a new MediaSession. MediaSessionCompat session = new MediaSessionCompat(this, "session tag"); setSessionToken(session.getSessionToken()); // Set a callback object that implements MediaSession.Callback // to handle play control requests. session.setCallback(new MyMediaSessionCallback()); ... }
Wenn Sie das Media-Sitzungsobjekt erstellen, legen Sie ein Callback-Objekt fest, das zum Verarbeiten von Anfragen zur Wiedergabesteuerung verwendet wird. Sie erstellen dieses Callback-Objekt, indem Sie eine Implementierung der Klasse MediaSessionCompat.Callback
für Ihre App bereitstellen. Im nächsten Abschnitt wird beschrieben, wie Sie dieses Objekt implementieren.
Wiedergabebefehle implementieren
Wenn ein Nutzer die Wiedergabe eines Media-Elements aus Ihrer App anfordert, verwenden Android Automotive OS und Android Auto die Klasse MediaSessionCompat.Callback
aus dem MediaSessionCompat
-Objekt Ihrer App, das sie vom Media-Browser-Dienst Ihrer App erhalten haben. Wenn ein Nutzer die Wiedergabe von Inhalten steuern möchte, z. B. die Wiedergabe pausieren oder zum nächsten Titel springen, rufen Android Auto und Android Automotive OS eine der Methoden des Callback-Objekts auf.
Für die Wiedergabe von Inhalten muss Ihre App die abstrakte Klasse MediaSessionCompat.Callback
erweitern und die von Ihrer App unterstützten Methoden implementieren.
Implementieren Sie alle folgenden Callback-Methoden, die für die Art von Inhalten, die Ihre App bietet, sinnvoll sind:
onPrepare()
- Wird aufgerufen, wenn die Media-Quelle geändert wird. Android Automotive OS ruft diese Methode auch unmittelbar nach dem Booten auf. Ihre Media-App muss diese Methode implementieren.
onPlay()
- Wird aufgerufen, wenn der Nutzer die Wiedergabe startet, ohne ein bestimmtes Element auszuwählen. Ihre App muss ihre Standardinhalte abspielen oder, wenn die Wiedergabe mit
onPause()
pausiert wurde, die Wiedergabe fortsetzen.Hinweis:Ihre App sollte nicht automatisch mit der Musikwiedergabe beginnen, wenn Android Automotive OS oder Android Auto eine Verbindung zu Ihrem Media Browser-Dienst herstellen. Weitere Informationen finden Sie im Abschnitt zum Festlegen des anfänglichen Wiedergabestatus.
onPlayFromMediaId()
- Wird aufgerufen, wenn der Nutzer ein bestimmtes Element auswählt, um es abzuspielen. Der Methode wird die ID übergeben, die Ihr Mediabrowserdienst dem Media-Element in Ihrer Inhaltshierarchie zugewiesen hat.
onPlayFromSearch()
- Wird aufgerufen, wenn der Nutzer die Wiedergabe über eine Suchanfrage startet. Die App muss eine geeignete Auswahl basierend auf dem übergebenen Suchstring treffen.
onPause()
- Wird aufgerufen, wenn der Nutzer die Wiedergabe pausiert.
onSkipToNext()
- Wird aufgerufen, wenn der Nutzer zum nächsten Element springen möchte.
onSkipToPrevious()
- Wird aufgerufen, wenn der Nutzer zum vorherigen Element springen möchte.
onStop()
- Wird aufgerufen, wenn der Nutzer die Wiedergabe beendet.
Überschreiben Sie diese Methoden in Ihrer App, um die gewünschten Funktionen bereitzustellen. Sie müssen keine Methode implementieren, wenn ihre Funktion von Ihrer App nicht unterstützt wird. Wenn Ihre App beispielsweise einen Livestream wie eine Sportübertragung wiedergibt, müssen Sie die Methode onSkipToNext()
nicht implementieren. Sie können stattdessen die Standardimplementierung von onSkipToNext()
verwenden.
Ihre App benötigt keine spezielle Logik, um Inhalte über die Lautsprecher des Autos abzuspielen. Wenn Ihre App eine Anfrage zum Abspielen von Inhalten erhält, kann sie Audioinhalte auf dieselbe Weise wiedergeben wie über die Lautsprecher oder Kopfhörer eines Smartphones. Android Auto und Android Automotive OS senden die Audioinhalte automatisch an das System des Autos, damit sie über die Lautsprecher des Autos wiedergegeben werden.
Weitere Informationen zur Wiedergabe von Audioinhalten finden Sie in der MediaPlayer-Übersicht, der Übersicht über Audio-Apps und der ExoPlayer-Übersicht.
Standard-Wiedergabeaktionen festlegen
Android Auto und Android Automotive OS zeigen die Wiedergabesteuerung basierend auf den Aktionen an, die im PlaybackStateCompat
-Objekt aktiviert sind.
Standardmäßig muss Ihre App die folgenden Aktionen unterstützen:
Ihre App kann zusätzlich die folgenden Aktionen unterstützen, sofern sie für die Inhalte der App relevant sind:
Außerdem haben Sie die Möglichkeit, eine Wiedergabeliste zu erstellen, die dem Nutzer angezeigt werden kann. Dies ist jedoch nicht erforderlich. Rufen Sie dazu die Methoden setQueue()
und setQueueTitle()
auf, aktivieren Sie die Aktion ACTION_SKIP_TO_QUEUE_ITEM
und definieren Sie den Callback onSkipToQueueItem()
.
Füge außerdem Unterstützung für das Symbol Now Playing (Wird gerade wiedergegeben) hinzu, das angibt, was gerade wiedergegeben wird. Rufen Sie dazu die Methode setActiveQueueItemId()
auf und übergeben Sie die ID des aktuell wiedergegebenen Elements in der Warteschlange. Sie müssen setActiveQueueItemId()
immer dann aktualisieren, wenn sich die Warteschlange ändert.
In Android Auto und Android Automotive OS werden Schaltflächen für jede aktivierte Aktion sowie die Wiedergabeliste angezeigt. Wenn auf die Schaltflächen geklickt wird, ruft das System den entsprechenden Callback von MediaSessionCompat.Callback
auf.
Nicht genutzten Speicherplatz reservieren
In Android Auto und Android Automotive OS wird in der Benutzeroberfläche Platz für die Aktionen ACTION_SKIP_TO_PREVIOUS
und ACTION_SKIP_TO_NEXT
reserviert. Wenn Ihre App eine dieser Funktionen nicht unterstützt, wird der Bereich in Android Auto und Android Automotive OS verwendet, um benutzerdefinierte Aktionen anzuzeigen, die Sie erstellen.
Wenn Sie diese Bereiche nicht mit benutzerdefinierten Aktionen füllen möchten, können Sie sie reservieren, damit Android Auto und Android Automotive OS den Bereich leer lassen, wenn Ihre App die entsprechende Funktion nicht unterstützt. Rufen Sie dazu die Methode setExtras()
mit einem Extras-Bundle auf, das Konstanten enthält, die den reservierten Funktionen entsprechen.
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
entspricht ACTION_SKIP_TO_NEXT
und SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
entspricht ACTION_SKIP_TO_PREVIOUS
. Verwenden Sie diese Konstanten als Schlüssel im Bundle und den booleschen Wert true
für ihre Werte.
Anfänglichen PlaybackState festlegen
Da Android Auto und Android Automotive OS mit Ihrem Media-Browser-Dienst kommunizieren, wird der Status der Wiedergabe von Inhalten über die PlaybackStateCompat
an Ihre Media-Session übermittelt.
Ihre App sollte nicht automatisch mit der Musikwiedergabe beginnen, wenn Android Automotive OS oder Android Auto eine Verbindung zu Ihrem MediaBrowserService herstellen. Verlassen Sie sich stattdessen auf Android Auto und Android Automotive OS, um die Wiedergabe basierend auf dem Status des Autos oder Nutzeraktionen fortzusetzen oder zu starten.
Setzen Sie dazu den anfänglichen PlaybackStateCompat
Ihrer Mediensitzung auf STATE_STOPPED
, STATE_PAUSED
, STATE_NONE
oder STATE_ERROR
.
Mediensitzungen in Android Auto und Android Automotive OS dauern nur so lange wie die Fahrt. Nutzer starten und beenden diese Sitzungen also häufig. Um einen nahtlosen Übergang zwischen Fahrten zu ermöglichen, sollten Sie den vorherigen Sitzungsstatus des Nutzers im Blick behalten. Wenn die Media-App eine Anfrage zum Fortsetzen erhält, kann der Nutzer automatisch dort weitermachen, wo er aufgehört hat, z. B. mit dem zuletzt wiedergegebenen Media-Element, der PlaybackStateCompat
und der Warteschlange.
Benutzerdefinierte Wiedergabeaktionen hinzufügen
Du kannst benutzerdefinierte Wiedergabeaktionen hinzufügen, um zusätzliche Aktionen anzuzeigen, die deine Media-App unterstützt. Wenn der Platz ausreicht (und nicht reserviert ist), fügt Android die benutzerdefinierten Aktionen den Transportsteuerungen hinzu. Andernfalls werden die benutzerdefinierten Aktionen im Dreipunkt-Menü angezeigt. Benutzerdefinierte Aktionen werden in der Reihenfolge angezeigt, in der sie der PlaybackStateCompat
hinzugefügt werden.
Mit benutzerdefinierten Aktionen können Sie ein Verhalten festlegen, das sich von Standardaktionen unterscheidet. Sie dürfen nicht verwendet werden, um Standardaktionen zu ersetzen oder zu duplizieren.
Mit der Methode addCustomAction()
in der Klasse PlaybackStateCompat.Builder
können Sie benutzerdefinierte Aktionen hinzufügen.
Das folgende Code-Snippet zeigt, wie Sie die benutzerdefinierte Aktion „Radiosender starten“ hinzufügen:
Kotlin
val customActionExtras = Bundle() customActionExtras.putInt( androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT, androidx.media3.session.CommandButton.ICON_RADIO) stateBuilder.addCustomAction( PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon // or R.drawable.media3_icon_radio ).run { setExtras(customActionExtras) build() } )
Java
Bundle customActionExtras = new Bundle(); customActionExtras.putInt( androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT, androidx.media3.session.CommandButton.ICON_RADIO); stateBuilder.addCustomAction( new PlaybackStateCompat.CustomAction.Builder( CUSTOM_ACTION_START_RADIO_FROM_MEDIA, resources.getString(R.string.start_radio_from_media), startRadioFromMediaIcon) // or R.drawable.media3_icon_radio .setExtras(customActionExtras) .build());
Ein detaillierteres Beispiel für diese Methode finden Sie in der setCustomAction()
-Methode in der Universal Android Music Player-Beispiel-App auf GitHub.
Nachdem Sie die benutzerdefinierte Aktion erstellt haben, kann Ihre Mediensitzung auf die Aktion reagieren, indem Sie die Methode onCustomAction()
überschreiben.
Das folgende Code-Snippet zeigt, wie Ihre App auf die Aktion „Starte einen Radiosender“ reagieren könnte:
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) { when(action) { CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> { ... } } }
Java
@Override public void onCustomAction(@NonNull String action, Bundle extras) { if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) { ... } }
Ein detaillierteres Beispiel für diese Methode finden Sie in der onCustomAction
-Methode in der Universal Android Music Player-Beispiel-App auf GitHub.
Symbole für benutzerdefinierte Aktionen
Für jede benutzerdefinierte Aktion, die Sie erstellen, ist ein Symbol erforderlich.
Wenn die Beschreibung dieses Symbols mit einer der CommandButton.ICON_
-Konstanten übereinstimmt, sollten Sie diesen Ganzzahlwert für den EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT
-Schlüssel der Extras der benutzerdefinierten Aktion festlegen. Auf unterstützten Systemen wird dadurch die an CustomAction.Builder
übergebene Symbolressource überschrieben, sodass Systemkomponenten Ihre Aktion und andere Wiedergabeaktionen in einem einheitlichen Stil rendern können.
Sie müssen auch eine Symbolressource angeben. Apps für Autos können auf vielen verschiedenen Bildschirmgrößen und ‑dichten ausgeführt werden. Daher müssen die von Ihnen bereitgestellten Symbole Vektordrawables sein. Mit einem Vektordrawable können Sie Assets skalieren, ohne dass Details verloren gehen. Mit einer Vektorgrafik lassen sich außerdem bei geringeren Auflösungen die Kanten und Ecken an die Pixelgrenzen anpassen.
Wenn eine benutzerdefinierte Aktion statusabhängig ist, z. B. eine Wiedergabeeinstellung aktiviert oder deaktiviert, stellen Sie verschiedene Symbole für die verschiedenen Status bereit, damit Nutzer eine Änderung sehen können, wenn sie die Aktion auswählen.
Alternative Symbolstile für deaktivierte Aktionen bereitstellen
Wenn eine benutzerdefinierte Aktion für den aktuellen Kontext nicht verfügbar ist, ersetzen Sie das Symbol für die benutzerdefinierte Aktion durch ein alternatives Symbol, das angibt, dass die Aktion deaktiviert ist.
Audioformat angeben
Wenn gerade wiedergegebene Medien ein spezielles Audioformat verwenden, können Sie Symbole angeben, die in Autos gerendert werden, die diese Funktion unterstützen. Sie können KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI
und KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI
im Extras-Bundle des aktuell wiedergegebenen Media-Elements festlegen, das an MediaSession.setMetadata()
übergeben wird. Achten Sie darauf, beide Extras festzulegen, um verschiedenen Layouts gerecht zu werden.
Außerdem kannst du das KEY_IMMERSIVE_AUDIO
-Extra festlegen, um Autohersteller darauf hinzuweisen, dass es sich um immersiven Audioinhalt handelt. Sie sollten daher sehr vorsichtig sein, wenn sie entscheiden, ob sie Audioeffekte anwenden, die die immersiven Inhalte beeinträchtigen könnten.
Links aus dem aktuell wiedergegebenen Element hinzufügen
Sie können das aktuell wiedergegebene Media-Element so konfigurieren, dass der Untertitel, die Beschreibung oder beides Links zu anderen Media-Elementen sind. So kann der Nutzer schnell zu ähnlichen Inhalten springen, z. B. zu anderen Songs desselben Künstlers oder anderen Folgen dieses Podcasts. Wenn das Auto diese Funktion unterstützt, können Nutzer auf den Link tippen, um diese Inhalte aufzurufen.
Wenn Sie Links hinzufügen möchten, konfigurieren Sie die Metadaten KEY_SUBTITLE_LINK_MEDIA_ID
(um über den Untertitel zu verlinken) oder KEY_DESCRIPTION_LINK_MEDIA_ID
(um über die Beschreibung zu verlinken). Weitere Informationen finden Sie in der Referenzdokumentation zu diesen Metadatenfeldern.
Sprachbefehle unterstützen
Ihre Media-App muss Sprachaktionen unterstützen, damit Fahrer eine sichere und komfortable Nutzung ohne Ablenkung haben. Wenn Ihre App beispielsweise ein Media-Element wiedergibt, kann der Nutzer „Play [song title]“ sagen, um Ihre App anzuweisen, einen anderen Song abzuspielen, ohne auf das Display des Autos zu schauen oder es zu berühren. Nutzer können Anfragen starten, indem sie auf die entsprechenden Tasten auf dem Lenkrad klicken oder die Hotwords Ok Google sagen.
Wenn Android Auto oder Android Automotive OS eine Sprachaktion erkennt und interpretiert, wird diese Sprachaktion über onPlayFromSearch()
an die App gesendet.
Nach Erhalt dieses Rückrufs sucht die App nach Inhalten, die dem String query
entsprechen, und startet die Wiedergabe.
Nutzer können in ihrer Anfrage verschiedene Kategorien von Begriffen angeben, z. B. Genre, Künstler, Album, Titelname, Radiosender oder Playlist. Berücksichtigen Sie beim Entwickeln der Unterstützung für die Suche alle Kategorien, die für Ihre App sinnvoll sind. Wenn Android Auto oder Android Automotive OS erkennt, dass eine bestimmte Anfrage in bestimmte Kategorien passt, werden Extras an den Parameter extras
angehängt. Folgende Extras können gesendet werden:
Berücksichtigen Sie einen leeren query
-String, der von Android Auto oder Android Automotive OS gesendet werden kann, wenn der Nutzer keine Suchbegriffe angibt.
Wenn der Nutzer beispielsweise sagt: Spiel Musik ab. In diesem Fall wird in Ihrer App möglicherweise ein kürzlich wiedergegebener oder neu vorgeschlagener Titel gestartet.
Wenn eine Suche nicht schnell verarbeitet werden kann, blockieren Sie sie nicht in onPlayFromSearch()
.
Stelle stattdessen den Wiedergabestatus auf STATE_CONNECTING
ein und führe die Suche in einem asynchronen Thread aus.
Sobald die Wiedergabe beginnt, kannst du die Warteschlange der Mediensitzung mit ähnlichen Inhalten füllen. Wenn der Nutzer beispielsweise die Wiedergabe eines Albums anfordert, kann deine App die Warteschlange mit der Titelliste des Albums füllen. Erwäge auch, durchsuchbare Suchergebnisse zu implementieren, damit Nutzer einen anderen Titel auswählen können, der ihrer Anfrage entspricht.
Neben „play“-Anfragen erkennen Android Auto und Android Automotive OS auch Sprachbefehle zur Steuerung der Wiedergabe wie „pause music“ (Musik pausieren) und „next song“ (nächster Song) und ordnen diese Befehle den entsprechenden MediaSession-Callbacks wie onPause()
und onSkipToNext()
zu.
Ein ausführliches Beispiel für die Implementierung von sprachgesteuerten Wiedergabeaktionen in Ihrer App finden Sie unter Google Assistant und Media-Apps.
Ablenkungsschutz implementieren
Da das Smartphone eines Nutzers bei der Verwendung von Android Auto mit den Lautsprechern des Autos verbunden ist, müssen Sie zusätzliche Vorsichtsmaßnahmen treffen, um Ablenkungen des Fahrers zu vermeiden.
Alarme im Auto unterdrücken
Android Auto-Media-Apps dürfen Audioinhalte nicht über die Autolautsprecher wiedergeben, es sei denn, der Nutzer startet die Wiedergabe, indem er beispielsweise eine Wiedergabetaste drückt. Auch ein vom Nutzer geplanter Wecker aus Ihrer Media-App darf nicht über die Autolautsprecher Musik abspielen.
Um diese Anforderung zu erfüllen, kann Ihre App CarConnection
als Signal verwenden, bevor Audio wiedergegeben wird. Ihre App kann prüfen, ob das Smartphone auf ein Autodisplay projiziert wird. Dazu muss sie LiveData
für den Verbindungstyp für das Auto beobachten und prüfen, ob er gleich CONNECTION_TYPE_PROJECTION
ist.
Wenn das Smartphone des Nutzers projiziert wird, müssen Media-Apps, die Alarme unterstützen, eine der folgenden Aktionen ausführen:
- Deaktivieren Sie den Alarm.
- Spiele den Wecker über
STREAM_ALARM
ab und stelle auf dem Smartphone-Display eine Benutzeroberfläche zum Deaktivieren des Weckers bereit.
Umgang mit Media-Werbung
Standardmäßig zeigt Android Auto eine Benachrichtigung an, wenn sich die Metadaten von Medien während der Audiowiedergabe ändern. Wenn eine Media-App von der Musikwiedergabe zur Ausführung einer Anzeige wechselt, ist es störend, dem Nutzer eine Benachrichtigung zu präsentieren. Damit Android Auto in diesem Fall keine Benachrichtigung anzeigt, müssen Sie den Media-Metadatenschlüssel METADATA_KEY_IS_ADVERTISEMENT
auf METADATA_VALUE_ATTRIBUTE_PRESENT
setzen, wie im folgenden Code-Snippet gezeigt:
Kotlin
import androidx.media.utils.MediaConstants override fun onPlayFromMediaId(mediaId: String, extras: Bundle?) { MediaMetadataCompat.Builder().apply { if (isAd(mediaId)) { putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT) } // ...add any other properties you normally would. mediaSession.setMetadata(build()) } }
Java
import androidx.media.utils.MediaConstants; @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); if (isAd(mediaId)) { builder.putLong( MediaConstants.METADATA_KEY_IS_ADVERTISEMENT, MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT); } // ...add any other properties you normally would. mediaSession.setMetadata(builder.build()); }
Allgemeine Fehler beheben
Wenn in der App ein Fehler auftritt, legen Sie den Wiedergabestatus auf STATE_ERROR
fest und geben Sie mit der Methode setErrorMessage()
eine Fehlermeldung an. Eine Liste der Fehlercodes, die Sie beim Festlegen der Fehlermeldung verwenden können, finden Sie unter PlaybackStateCompat
.
Fehlermeldungen müssen für den Nutzer sichtbar und in der aktuellen Sprache des Nutzers lokalisiert sein. Android Auto und Android Automotive OS können dem Nutzer dann die Fehlermeldung anzeigen.
Wenn Inhalte beispielsweise in der aktuellen Region des Nutzers nicht verfügbar sind, können Sie den Fehlercode ERROR_CODE_NOT_AVAILABLE_IN_REGION
verwenden, wenn Sie die Fehlermeldung festlegen.
Kotlin
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build())
Java
mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_ERROR) .setErrorMessage(PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION, getString(R.string.error_unsupported_region)) // ...and any other setters. .build());
Weitere Informationen zu Fehlerstatus finden Sie unter Mediensitzung verwenden: Status und Fehler.
Wenn ein Android Auto-Nutzer Ihre Smartphone-App öffnen muss, um einen Fehler zu beheben, geben Sie diese Information in Ihrer Nachricht an. Ihre Fehlermeldung könnte beispielsweise „Melden Sie sich in [Name Ihrer App] an“ anstelle von „Bitte melden Sie sich an“ lauten.