Android Auto und Android Automotive OS (AAOS) rufen den Media Browser-Dienst deiner App auf, um herauszufinden, welche Inhalte verfügbar sind. Dazu implementierst du diese beiden Methoden in deinem Media Browser-Dienst.
onGetRoot implementieren
Die Methode onGetRoot deines Dienstes gibt Informationen zum Stammknoten
deiner Inhaltshierarchie zurück. Android Auto und AAOS verwenden diesen Stamm
Knoten, um die restlichen Inhalte mit der onLoadChildren
Methode anzufordern. Dieser Code-Snippet zeigt eine 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 detailliertes Beispiel für diese Methode findest du unter onGetRoot in der Beispiel-App Universal
Android Music Player auf GitHub.
Paketvalidierung hinzufügen
Wenn ein Aufruf an die Methode onGetRoot deines Dienstes erfolgt, übergibt das aufrufende
Paket Identifikationsinformationen an deinen Dienst. Dein Dienst kann anhand dieser Informationen entscheiden, ob das Paket auf deine Inhalte zugreifen darf.
Du kannst beispielsweise den Zugriff auf die Inhalte deiner App auf eine Liste genehmigter Pakete beschränken:
- Vergleiche
clientPackageNamemit deiner Zulassungsliste. - Prüfe das Zertifikat, mit dem die APK für das Paket signiert wurde.
Wenn das Paket nicht verifiziert werden kann, gib null zurück, um den Zugriff auf deine Inhalte zu verweigern.
Damit System-Apps wie Android Auto und AAOS auf deine Inhalte zugreifen können, muss dein Dienst ein BrowserRoot zurückgeben, das nicht null ist, wenn diese System-Apps die Methode onGetRoot aufrufen.
Die Signatur der AAOS-System-App variiert je nach Marke und Modell eines Autos. Achte darauf, Verbindungen von allen System-Apps zuzulassen, um AAOS zu unterstützen.
Dieser Code-Snippet zeigt, wie dein 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
}
Dieser Code-Snippet ist ein Auszug aus der PackageValidator Klasse in der
Beispiel-App Universal Android Music Player auf GitHub. In dieser Klasse findest du ein detaillierteres Beispiel dafür, wie du die Paketvalidierung für die Methode onGetRoot deines Dienstes implementierst.
Neben System-Apps musst du auch Google Assistant erlauben, eine Verbindung zu deinem MediaBrowserService herzustellen. Google Assistant verwendet unterschiedliche Paketnamen
für seine mobilen Apps und AAOS-Apps.
onLoadChildren implementieren
Nachdem Android Auto und AAOS dein Stammknotenobjekt erhalten haben,
erstellen sie ein Menü der obersten Ebene, indem sie onLoadChildren für das Stammknotenobjekt aufrufen,
um seine Nachfolger abzurufen. Client-Apps erstellen Untermenüs, indem sie dieselbe Methode mit Nachfolgerknotenobjekten aufrufen.
Jeder Knoten in deiner Inhaltshierarchie wird durch ein
MediaBrowserCompat.MediaItem-Objekt dargestellt. Jedes dieser MediaItems wird durch einen eindeutigen ID-String identifiziert. Client-Apps behandeln diese ID-Strings als undurchsichtige Tokens.
Wenn eine Client-App zu einem Untermenü wechseln oder ein MediaItem abspielen möchte, übergibt sie das Token. Deine App ist dafür verantwortlich, das Token dem entsprechenden MediaItem zuzuordnen.
Dieser Code-Snippet zeigt eine Implementierung von 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 if 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 descendants 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 if 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 descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems);
}
Ein Beispiel für diese Methode findest du unter onLoadChildren in der
Beispiel-App Universal Android Music Player auf GitHub.
Struktur des Stammmenüs
Android Auto und Android Automotive OS haben bestimmte Einschränkungen hinsichtlich der Struktur des Stammmenüs. Diese werden dem MediaBrowserService über Stammhinweise mitgeteilt, die über das Bundle-Argument gelesen werden können, das an onGetRoot() übergeben wird. Wenn diese Hinweise befolgt werden, kann das System die Stamm-Inhalte als Navigationstabs anzeigen. Wenn du diese Hinweise nicht befolgst, werden einige Stamm-Inhalte möglicherweise vom System entfernt oder weniger auffindbar gemacht.

Abbildung 1 : Stamm-Inhalte, die als Navigationstabs angezeigt werden.
Wenn du diese Hinweise anwendest, zeigt das System die Stamm-Inhalte als Navigationstabs an. Wenn du diese Hinweise nicht anwendest, werden einige Stamm-Inhalte möglicherweise entfernt oder weniger auffindbar gemacht. Diese Hinweise werden übertragen:
Beschränkung der Anzahl der Stamm-Nachfolger: In den meisten Fällen ist diese Zahl vier. Das bedeutet, dass nur vier (oder weniger) Tabs angezeigt werden können.
Unterstützte Flags für die Stamm-Nachfolger: Dieser Wert sollte
MediaItem#FLAG_BROWSABLEsein. Das bedeutet, dass nur durchsuchbare Elemente (keine abspielbaren Elemente) als Tabs angezeigt werden können.Beschränkung der Anzahl der benutzerdefinierten Suchaktionen: Prüfe, wie viele benutzerdefinierte Suchaktionen unterstützt werden.
Kotlin
import androidx.media.utils.MediaConstants
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...
}
Du kannst die Logik für die Struktur deiner Inhaltshierarchie basierend auf den Werten dieser Hinweise verzweigen, insbesondere wenn sich deine Hierarchie zwischen MediaBrowser-Integrationen außerhalb von Android Auto und AAOS unterscheidet.
Wenn du beispielsweise normalerweise ein abspielbares Stamm-Element anzeigst, solltest du es aufgrund des Hinweises zu den unterstützten Flags stattdessen unter einem durchsuchbaren Stamm-Element verschachteln.
Neben Stammhinweisen kannst du diese Richtlinien verwenden, um Tabs optimal zu rendern:
Monochrome (vorzugsweise weiße) Symbole für jedes Tab-Element
Kurze und aussagekräftige Labels für jedes Tab-Element (kurze Labels verringern die Wahrscheinlichkeit, dass Labels abgeschnitten werden)