Die Mediensteuerung in Android befindet sich in der Nähe der Schnelleinstellungen. Sitzungen ab Mehrere Apps sind in einem wischbaren Karussell angeordnet. Das Karussell enthält Sitzungen in dieser Reihenfolge:
- Streams, die lokal auf dem Smartphone wiedergegeben werden
- Remote-Streams, z. B. von externen Geräten oder Streamingsitzungen erkannte Streams
- Vorherige fortsetzbare Sitzungen in der Reihenfolge, in der sie zuletzt gespielt wurden
Ab Android 13 (API-Level 33), damit Nutzer auf umfassende
Mediensteuerung für Apps, die Medien wiedergeben, Aktionsschaltflächen bei der Mediensteuerung
werden aus dem Status Player
abgeleitet.
So können Sie einheitliche Mediensteuerelemente und ein ausgefeilteres Mediensteuerung geräteübergreifend.
Abbildung 1 zeigt ein Beispiel dafür, wie dies auf einem Smartphone und Tablet aussieht. .
<ph type="x-smartling-placeholder">Das System zeigt je nach Status Player
bis zu fünf Aktionsschaltflächen an:
wie in der folgenden Tabelle beschrieben. Im kompakten Modus sind nur die ersten drei Aktionen
werden angezeigt. Das entspricht der Darstellung
der Mediensteuerelemente in anderen
Android-Plattformen wie Auto, Assistant und Wear OS
Stellen | Kriterien | Aktion |
---|---|---|
1 |
playWhenReady
„false“ ist oder die aktuelle Wiedergabe
Bundesland ist STATE_ENDED .
|
Wiedergeben |
playWhenReady ist „true“ und der aktuelle Wiedergabestatus ist STATE_BUFFERING .
|
Rotierendes Ladesymbol | |
playWhenReady ist „true“ und der aktuelle Wiedergabestatus ist STATE_READY . |
Pausieren | |
2 | Player-Befehl COMMAND_SEEK_TO_PREVIOUS oder COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM ist verfügbar. |
Zurück |
Weder der Player-Befehl COMMAND_SEEK_TO_PREVIOUS noch COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM ist verfügbar. Außerdem ist ein benutzerdefinierter Befehl aus dem benutzerdefinierten Layout, der noch nicht platziert wurde, zum Füllen der Anzeigenfläche verfügbar. |
Benutzerdefiniert | |
(noch nicht unterstützt bei Media3) PlaybackState -Extras beinhalten einen booleschen Wert true für den Schlüssel EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_PREV . |
Leer | |
3 | Player-Befehl COMMAND_SEEK_TO_NEXT oder COMMAND_SEEK_TO_NEXT_MEDIA_ITEM ist verfügbar. |
Weiter |
Weder der Player-Befehl COMMAND_SEEK_TO_NEXT noch COMMAND_SEEK_TO_NEXT_MEDIA_ITEM ist verfügbar. Außerdem ist ein benutzerdefinierter Befehl aus dem benutzerdefinierten Layout, der noch nicht platziert wurde, zum Füllen der Anzeigenfläche verfügbar. |
Benutzerdefiniert | |
(noch nicht unterstützt bei Media3) PlaybackState -Extras beinhalten einen booleschen Wert true für den Schlüssel EXTRAS_KEY_SLOT_RESERVATION_SEEK_TO_NEXT . |
Leer | |
4 | Ein benutzerdefinierter Befehl aus dem benutzerdefinierten Layout, der noch nicht platziert wurde, ist zum Füllen der Anzeigenfläche verfügbar. | Benutzerdefiniert |
5 | Ein benutzerdefinierter Befehl aus dem benutzerdefinierten Layout, der noch nicht platziert wurde, ist zum Füllen der Anzeigenfläche verfügbar. | Benutzerdefiniert |
Benutzerdefinierte Befehle werden in der Reihenfolge platziert, in der sie zum benutzerdefiniertes Layout.
Befehlsschaltflächen anpassen
So passen Sie die Mediensteuerung des Systems mit Jetpack Media3 an:
können Sie das benutzerdefinierte Layout der Sitzung und die verfügbaren Befehle
für die Verantwortlichen bei der Implementierung einer MediaSessionService
:
In
onCreate()
eineMediaSession
erstellen und das benutzerdefinierte Layout definieren von Befehlsschaltflächen.In
MediaSession.Callback.onConnect()
: Controller autorisieren, indem sie ihre verfügbaren Befehle definieren, einschließlich benutzerdefinierte Befehle, inConnectionResult
.In
MediaSession.Callback.onCustomCommand()
: auf den vom Nutzer ausgewählten benutzerdefinierten Befehl antworten.
Kotlin
class PlaybackService : MediaSessionService() { private val customCommandFavorites = SessionCommand(ACTION_FAVORITES, Bundle.EMPTY) private var mediaSession: MediaSession? = null override fun onCreate() { super.onCreate() val favoriteButton = CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(customCommandFavorites) .build() val player = ExoPlayer.Builder(this).build() // Build the session with a custom layout. mediaSession = MediaSession.Builder(this, player) .setCallback(MyCallback()) .setCustomLayout(ImmutableList.of(favoriteButton)) .build() } private inner class MyCallback : MediaSession.Callback { override fun onConnect( session: MediaSession, controller: MediaSession.ControllerInfo ): ConnectionResult { // Set available player and session commands. return AcceptedResultBuilder(session) .setAvailablePlayerCommands( ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon() .remove(COMMAND_SEEK_TO_NEXT) .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) .remove(COMMAND_SEEK_TO_PREVIOUS) .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM) .build() ) .setAvailableSessionCommands( ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(customCommandFavorites) .build() ) .build() } override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle ): ListenableFuture{ if (customCommand.customAction == ACTION_FAVORITES) { // Do custom logic here saveToFavorites(session.player.currentMediaItem) return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS)) } return super.onCustomCommand(session, controller, customCommand, args) } } }
Java
public class PlaybackService extends MediaSessionService { private static final SessionCommand CUSTOM_COMMAND_FAVORITES = new SessionCommand("ACTION_FAVORITES", Bundle.EMPTY); @Nullable private MediaSession mediaSession; public void onCreate() { super.onCreate(); CommandButton favoriteButton = new CommandButton.Builder() .setDisplayName("Save to favorites") .setIconResId(R.drawable.favorite_icon) .setSessionCommand(CUSTOM_COMMAND_FAVORITES) .build(); Player player = new ExoPlayer.Builder(this).build(); // Build the session with a custom layout. mediaSession = new MediaSession.Builder(this, player) .setCallback(new MyCallback()) .setCustomLayout(ImmutableList.of(favoriteButton)) .build(); } private static class MyCallback implements MediaSession.Callback { @Override public ConnectionResult onConnect( MediaSession session, MediaSession.ControllerInfo controller) { // Set available player and session commands. return new AcceptedResultBuilder(session) .setAvailablePlayerCommands( ConnectionResult.DEFAULT_PLAYER_COMMANDS.buildUpon() .remove(COMMAND_SEEK_TO_NEXT) .remove(COMMAND_SEEK_TO_NEXT_MEDIA_ITEM) .remove(COMMAND_SEEK_TO_PREVIOUS) .remove(COMMAND_SEEK_TO_PREVIOUS_MEDIA_ITEM) .build()) .setAvailableSessionCommands( ConnectionResult.DEFAULT_SESSION_COMMANDS.buildUpon() .add(CUSTOM_COMMAND_FAVORITES) .build()) .build(); } public ListenableFutureonCustomCommand( MediaSession session, MediaSession.ControllerInfo controller, SessionCommand customCommand, Bundle args) { if (customCommand.customAction.equals(CUSTOM_COMMAND_FAVORITES.customAction)) { // Do custom logic here saveToFavorites(session.getPlayer().getCurrentMediaItem()); return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_SUCCESS)); } return MediaSession.Callback.super.onCustomCommand( session, controller, customCommand, args); } } }
Weitere Informationen zur Konfiguration von MediaSession
, damit Clients wie die
System eine Verbindung zu Ihrer Medien-App herstellen kann, finden Sie
Anderen Clients die Kontrolle gewähren
Wenn Sie mit Jetpack Media3 eine MediaSession
implementieren, wird Ihre PlaybackState
wird automatisch über den Mediaplayer auf dem neuesten Stand gehalten. Ähnlich verhält es sich, wenn Sie
implementieren MediaSessionService
, veröffentlicht die Bibliothek automatisch eine
MediaStyle
Benachrichtigung
und hält sie auf dem neuesten Stand.
Auf Aktionsschaltflächen reagieren
Wenn ein Nutzer in der Mediensteuerung des Systems auf eine Aktionsschaltfläche tippt,
MediaController
sendet einen Wiedergabebefehl an MediaSession
. Die
MediaSession
delegiert diese Befehle dann an den Player. Befehle
definiert in Player
von Media3
werden automatisch von den Medien
Sitzung.
Weitere Informationen finden Sie unter Benutzerdefinierte Befehle hinzufügen. finden Sie eine Anleitung zum Antworten auf einen benutzerdefinierten Befehl.
Verhalten vor Android 13
Aus Gründen der Abwärtskompatibilität bietet die System-UI weiterhin ein alternatives Layout,
die Benachrichtigungsaktionen für Apps nutzt,
die nicht auf Android 13 aktualisiert werden,
oder keine Informationen zu PlaybackState
enthalten. Die Aktionsschaltflächen sind
abgeleitet aus der Liste Notification.Action
, die an MediaStyle
angehängt ist
Benachrichtigung. Das System zeigt bis zu fünf Aktionen in der Reihenfolge an, in der sie
wurden hinzugefügt. Im kompakten Modus werden bis zu drei Schaltflächen angezeigt.
Werte, die an setShowActionsInCompactView()
übergeben werden.
Benutzerdefinierte Aktionen werden in der Reihenfolge platziert, in der sie zum
PlaybackState
Das folgende Codebeispiel zeigt, wie Aktionen zu MediaStyle hinzugefügt werden. Benachrichtigung :
Kotlin
import androidx.core.app.NotificationCompat import androidx.media3.session.MediaStyleNotificationHelper var notification = NotificationCompat.Builder(context, CHANNEL_ID) // Show controls on lock screen even when user hides sensitive content. .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setSmallIcon(R.drawable.ic_stat_player) // Add media control buttons that invoke intents in your media service .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) // #0 .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) // #1 .addAction(R.drawable.ic_next, "Next", nextPendingIntent) // #2 // Apply the media style template .setStyle(MediaStyleNotificationHelper.MediaStyle(mediaSession) .setShowActionsInCompactView(1 /* #1: pause button */)) .setContentTitle("Wonderful music") .setContentText("My Awesome Band") .setLargeIcon(albumArtBitmap) .build()
Java
import androidx.core.app.NotificationCompat; import androidx.media3.session.MediaStyleNotificationHelper; NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setSmallIcon(R.drawable.ic_stat_player) .addAction(R.drawable.ic_prev, "Previous", prevPendingIntent) .addAction(R.drawable.ic_pause, "Pause", pausePendingIntent) .addAction(R.drawable.ic_next, "Next", nextPendingIntent) .setStyle(new MediaStyleNotificationHelper.MediaStyle(mediaSession) .setShowActionsInCompactView(1 /* #1: pause button */)) .setContentTitle("Wonderful music") .setContentText("My Awesome Band") .setLargeIcon(albumArtBitmap) .build();
Wiederaufnahme von Medien unterstützen
Die Wiederaufnahme von Medien ermöglicht es Nutzern, vorherige Sitzungen aus dem Karussell neu zu starten. ohne die App starten zu müssen. Zu Beginn der Wiedergabe interagiert der Nutzer mit die Mediensteuerung wie gewohnt.
Die Funktion zur Wiederaufnahme der Wiedergabe kann über die App "Einstellungen" aktiviert und deaktiviert werden. unter Ton > Medienoptionen Der Nutzer kann auch folgendermaßen auf die Einstellungen zugreifen: Tippen Sie auf das Zahnradsymbol, das nach dem Wischen über das maximierte Karussell erscheint.
Media3 bietet APIs für eine einfachere Wiederaufnahme von Medien. Weitere Informationen finden Sie in der Wiederaufnahme der Wiedergabe mit Media3 Dokumentation zur Implementierung dieser Funktion.
Legacy-Medien-APIs verwenden
In diesem Abschnitt wird erläutert, wie die Mediensteuerung des Systems mithilfe von der alten MediaCompat-APIs.
Das System ruft die folgenden Informationen aus dem
MediaMetadata
von MediaSession
und zeigt ihn an, wenn er verfügbar ist:
METADATA_KEY_ALBUM_ART_URI
METADATA_KEY_TITLE
METADATA_KEY_DISPLAY_TITLE
METADATA_KEY_ARTIST
METADATA_KEY_DURATION
(Wenn die Dauer nicht festgelegt ist, wird die Steuerleiste nicht Fortschritt anzeigen)
Damit Sie eine gültige und korrekte Benachrichtigung zur Mediensteuerung erhalten,
Wert von METADATA_KEY_TITLE
oder METADATA_KEY_DISPLAY_TITLE
festlegen
Metadaten zum Titel der gerade abgespielten Medien.
Im Mediaplayer wird die verstrichene Zeit für die aktuell wiedergegebene
Medium, zusammen mit einer Steuerleiste, die der MediaSession
PlaybackState
.
Der Mediaplayer zeigt den Fortschritt der aktuell wiedergegebenen Medien an.
Eine Steuerleiste, die MediaSession
PlaybackState
zugeordnet ist. Steuerleiste
können Nutzer die Position ändern und die verstrichene Zeit für die Medien anzeigen.
ein. Um die Suchleiste zu aktivieren, müssen Sie
PlaybackState.Builder#setActions
und ACTION_SEEK_TO
.
Stellen | Aktion | Kriterien |
---|---|---|
1 | Wiedergeben |
Der aktuelle Status des PlaybackState ist einer der folgenden:
<ph type="x-smartling-placeholder">
|
Rotierendes Ladesymbol |
Der aktuelle Status des PlaybackState ist einer der folgenden:
<ph type="x-smartling-placeholder">
|
|
Pausieren | Der aktuelle Status von PlaybackState entspricht keinem der oben genannten Werte. |
|
2 | Zurück | PlaybackState Aktionen umfassen ACTION_SKIP_TO_PREVIOUS . |
Benutzerdefiniert | PlaybackState Aktionen enthalten ACTION_SKIP_TO_PREVIOUS nicht und PlaybackState benutzerdefinierte Aktionen enthalten eine benutzerdefinierte Aktion, die noch nicht platziert wurde. |
|
Leer | PlaybackState -Extras enthalten einen booleschen Wert für true für den Schlüssel SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV . |
|
3 | Weiter | PlaybackState Aktionen umfassen ACTION_SKIP_TO_NEXT . |
Benutzerdefiniert | PlaybackState Aktionen enthalten ACTION_SKIP_TO_NEXT nicht und PlaybackState benutzerdefinierte Aktionen enthalten eine benutzerdefinierte Aktion, die noch nicht platziert wurde. |
|
Leer | PlaybackState -Extras enthalten einen booleschen Wert für true für den Schlüssel SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT . |
|
4 | Benutzerdefiniert | PlaybackState benutzerdefinierte Aktionen enthalten eine benutzerdefinierte Aktion, die noch nicht platziert wurde. |
5 | Benutzerdefiniert | PlaybackState benutzerdefinierte Aktionen enthalten eine benutzerdefinierte Aktion, die noch nicht platziert wurde. |
Standardaktionen hinzufügen
Die folgenden Codebeispiele veranschaulichen, wie Sie PlaybackState
-Standard- und
benutzerdefinierten Aktionen.
Für Wiedergabe, Pause, Zurück und Weiter legen Sie diese Aktionen in
Den PlaybackState
für die Mediensitzung.
Kotlin
val session = MediaSessionCompat(context, TAG) val playbackStateBuilder = PlaybackStateCompat.Builder() val style = NotificationCompat.MediaStyle() // For this example, the media is currently paused: val state = PlaybackStateCompat.STATE_PAUSED val position = 0L val playbackSpeed = 1f playbackStateBuilder.setState(state, position, playbackSpeed) // And the user can play, skip to next or previous, and seek val stateActions = PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PLAY_PAUSE or PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or PlaybackStateCompat.ACTION_SKIP_TO_NEXT or PlaybackStateCompat.ACTION_SEEK_TO // adding the seek action enables seeking with the seekbar playbackStateBuilder.setActions(stateActions) // ... do more setup here ... session.setPlaybackState(playbackStateBuilder.build()) style.setMediaSession(session.sessionToken) notificationBuilder.setStyle(style)
Java
MediaSessionCompat session = new MediaSessionCompat(context, TAG); PlaybackStateCompat.Builder playbackStateBuilder = new PlaybackStateCompat.Builder(); NotificationCompat.MediaStyle style = new NotificationCompat.MediaStyle(); // For this example, the media is currently paused: int state = PlaybackStateCompat.STATE_PAUSED; long position = 0L; float playbackSpeed = 1f; playbackStateBuilder.setState(state, position, playbackSpeed); // And the user can play, skip to next or previous, and seek long stateActions = PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS | PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SEEK_TO; // adding this enables the seekbar thumb playbackStateBuilder.setActions(stateActions); // ... do more setup here ... session.setPlaybackState(playbackStateBuilder.build()); style.setMediaSession(session.getSessionToken()); notificationBuilder.setStyle(style);
Sollen für die vorherige oder die nächste Anzeigenfläche keine Schaltflächen angezeigt werden, fügen Sie
ACTION_SKIP_TO_PREVIOUS
oder ACTION_SKIP_TO_NEXT
. Fügen Sie stattdessen Extras zu
Sitzung:
Kotlin
session.setExtras(Bundle().apply { putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV, true) putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT, true) })
Java
Bundle extras = new Bundle(); extras.putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV, true); extras.putBoolean(SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT, true); session.setExtras(extras);
Benutzerdefinierte Aktionen hinzufügen
Für andere Aktionen, die Sie in den Mediensteuerelementen anzeigen möchten, können Sie ein
PlaybackStateCompat.CustomAction
und fügen Sie ihn stattdessen dem PlaybackState
hinzu. Diese Aktionen werden in der
in der sie hinzugefügt wurden.
Kotlin
val customAction = PlaybackStateCompat.CustomAction.Builder( "com.example.MY_CUSTOM_ACTION", // action ID "Custom Action", // title - used as content description for the button R.drawable.ic_custom_action ).build() playbackStateBuilder.addCustomAction(customAction)
Java
PlaybackStateCompat.CustomAction customAction = new PlaybackStateCompat.CustomAction.Builder( "com.example.MY_CUSTOM_ACTION", // action ID "Custom Action", // title - used as content description for the button R.drawable.ic_custom_action ).build(); playbackStateBuilder.addCustomAction(customAction);
Auf Aktionen für Wiedergabestatus reagieren
Wenn Nutzende auf eine Schaltfläche tippen, verwendet SystemUI
MediaController.TransportControls
um einen Befehl an MediaSession
zurückzusenden. Du musst einen Callback registrieren
die entsprechend reagieren können.
Kotlin
val callback = object: MediaSession.Callback() { override fun onPlay() { // start playback } override fun onPause() { // pause playback } override fun onSkipToPrevious() { // skip to previous } override fun onSkipToNext() { // skip to next } override fun onSeekTo(pos: Long) { // jump to position in track } override fun onCustomAction(action: String, extras: Bundle?) { when (action) { CUSTOM_ACTION_1 -> doCustomAction1(extras) CUSTOM_ACTION_2 -> doCustomAction2(extras) else -> { Log.w(TAG, "Unknown custom action $action") } } } } session.setCallback(callback)
Java
MediaSession.Callback callback = new MediaSession.Callback() { @Override public void onPlay() { // start playback } @Override public void onPause() { // pause playback } @Override public void onSkipToPrevious() { // skip to previous } @Override public void onSkipToNext() { // skip to next } @Override public void onSeekTo(long pos) { // jump to position in track } @Override public void onCustomAction(String action, Bundle extras) { if (action.equals(CUSTOM_ACTION_1)) { doCustomAction1(extras); } else if (action.equals(CUSTOM_ACTION_2)) { doCustomAction2(extras); } else { Log.w(TAG, "Unknown custom action " + action); } } };
Medienwiederaufnahme
So sorgst du dafür, dass deine App im Bereich mit den Schnelleinstellungen angezeigt wird:
Sie müssen eine MediaStyle
-Benachrichtigung mit einem gültigen MediaSession
-Token erstellen.
Um den Titel für die MediaStyle-Benachrichtigung anzuzeigen, verwenden Sie
NotificationBuilder.setContentTitle()
Um das Markensymbol für den Mediaplayer anzuzeigen, verwenden Sie
NotificationBuilder.setSmallIcon()
Apps müssen eine MediaBrowserService
implementieren, um die Wiederaufnahme der Wiedergabe zu unterstützen
und MediaSession
. Dein MediaSession
muss den onPlay()
-Callback implementieren.
MediaBrowserService
-Implementierung
Nach dem Hochfahren sucht das System nach den fünf zuletzt verwendeten Medien. Apps und bietet Steuerelemente, mit denen die Wiedergabe aus jeder App neu gestartet werden kann.
Das System versucht, MediaBrowserService
über eine Verbindung von
SystemUI Deine App muss solche Verbindungen zulassen, andernfalls unterstützt sie keine
Wiedergabe fortgesetzt.
Verbindungen von SystemUI können anhand des Paketnamens identifiziert und verifiziert werden
com.android.systemui
und Signatur. Die SystemUI ist mit der Plattform signiert.
Signatur. Ein Beispiel für den Abgleich mit der Plattformsignatur ist:
Sie finden sie in der UAMP App.
Um die Wiederaufnahme der Wiedergabe zu unterstützen, muss dein MediaBrowserService
folgende Verhaltensweisen implementieren:
onGetRoot()
muss schnell einen Stamm ungleich null zurückgeben. Andere komplexe Logik sollteonLoadChildren()
bearbeitet werdenWann?
onLoadChildren()
auf der Stamm-Media-ID aufgerufen wird, muss das Ergebnis einen FLAG_PLAYABLE Kind.MediaBrowserService
sollte das zuletzt wiedergegebene Medienelement zurückgeben, wenn erhalten sie eine EXTRA_LETZT Abfrage. Der zurückgegebene Wert sollte ein tatsächliches Medienelement und kein generischer Wert sein. .MediaBrowserService
muss eine entsprechende MediaDescription mit einer nicht leeren Beschreibung title und Untertitel. Außerdem sollte ein Symbol-URI oder Bitmap des Symbols.
Die folgenden Codebeispiele veranschaulichen, wie onGetRoot()
implementiert wird.
Kotlin
override fun onGetRoot( clientPackageName: String, clientUid: Int, rootHints: Bundle? ): BrowserRoot? { ... // Verify that the specified package is SystemUI. You'll need to write your // own logic to do this. if (isSystem(clientPackageName, clientUid)) { rootHints?.let { if (it.getBoolean(BrowserRoot.EXTRA_RECENT)) { // Return a tree with a single playable media item for resumption. val extras = Bundle().apply { putBoolean(BrowserRoot.EXTRA_RECENT, true) } return BrowserRoot(MY_RECENTS_ROOT_ID, extras) } } // You can return your normal tree if the EXTRA_RECENT flag is not present. return BrowserRoot(MY_MEDIA_ROOT_ID, null) } // Return an empty tree to disallow browsing. return BrowserRoot(MY_EMPTY_ROOT_ID, null)
Java
@Override public BrowserRoot onGetRoot(String clientPackageName, int clientUid, Bundle rootHints) { ... // Verify that the specified package is SystemUI. You'll need to write your // own logic to do this. if (isSystem(clientPackageName, clientUid)) { if (rootHints != null) { if (rootHints.getBoolean(BrowserRoot.EXTRA_RECENT)) { // Return a tree with a single playable media item for resumption. Bundle extras = new Bundle(); extras.putBoolean(BrowserRoot.EXTRA_RECENT, true); return new BrowserRoot(MY_RECENTS_ROOT_ID, extras); } } // You can return your normal tree if the EXTRA_RECENT flag is not present. return new BrowserRoot(MY_MEDIA_ROOT_ID, null); } // Return an empty tree to disallow browsing. return new BrowserRoot(MY_EMPTY_ROOT_ID, null); }