Um das Client/Server-Design fertigzustellen, müssen Sie eine Aktivitätskomponente erstellen, die Ihren Benutzeroberflächencode, einen zugehörigen MediaController und einen MediaBrowser enthält.
Der MediaBrowser führt zwei wichtige Funktionen aus: Er stellt eine Verbindung zu einem MediaBrowserService her und erstellt nach dem Herstellen der Verbindung das MediaController-Element für Ihre Benutzeroberfläche.
Hinweis : Die empfohlene Implementierung von MediaBrowser
ist MediaBrowserCompat
,
die in den
Media-Compat-Supportbibliothek.
Auf dieser Seite wird der Begriff "MediaBrowser" bezieht sich auf eine Instanz
MediaBrowserCompat.
Verbindung zum MediaBrowserService herstellen
Wenn Ihre Clientaktivität erstellt wird, stellt sie eine Verbindung zum MediaBrowserService her. Dabei geht es um Handschlag und Tanz. Ändern Sie die Lebenszyklus-Callbacks der Aktivität so:
onCreate()
erstellt einen MediaBrowserCompat. Übergeben Sie den von Ihnen definierten Namen von MediaBrowserService und MediaBrowserCompat.ConnectionCallback.onStart()
stellt eine Verbindung zum MediaBrowserService her. Hier kommt die Magie von MediaBrowserCompat.ConnectionCallback ins Spiel. Wenn die Verbindung erfolgreich hergestellt wurde, erstellt der onConnect()-Callback den Medien-Controller und verknüpft ihn mit der Mediensitzung, verknüpft Ihre UI-Steuerelemente mit dem MediaController und registriert den Controller, um Rückrufe von der Mediensitzung zu empfangen.onResume()
legt den Audiostream so fest, dass deine App auf die Lautstärkeregelung auf dem Gerät reagiert.onStop()
trennt die Verbindung zu MediaBrowser und hebt die Registrierung von MediaController.Callback auf, wenn die Aktivität beendet wird.
Kotlin
class MediaPlayerActivity : AppCompatActivity() { private lateinit var mediaBrowser: MediaBrowserCompat override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // Create MediaBrowserServiceCompat mediaBrowser = MediaBrowserCompat( this, ComponentName(this, MediaPlaybackService::class.java), connectionCallbacks, null // optional Bundle ) } public override fun onStart() { super.onStart() mediaBrowser.connect() } public override fun onResume() { super.onResume() volumeControlStream = AudioManager.STREAM_MUSIC } public override fun onStop() { super.onStop() // (see "stay in sync with the MediaSession") MediaControllerCompat.getMediaController(this)?.unregisterCallback(controllerCallback) mediaBrowser.disconnect() } }
Java
public class MediaPlayerActivity extends AppCompatActivity { private MediaBrowserCompat mediaBrowser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // Create MediaBrowserServiceCompat mediaBrowser = new MediaBrowserCompat(this, new ComponentName(this, MediaPlaybackService.class), connectionCallbacks, null); // optional Bundle } @Override public void onStart() { super.onStart(); mediaBrowser.connect(); } @Override public void onResume() { super.onResume(); setVolumeControlStream(AudioManager.STREAM_MUSIC); } @Override public void onStop() { super.onStop(); // (see "stay in sync with the MediaSession") if (MediaControllerCompat.getMediaController(MediaPlayerActivity.this) != null) { MediaControllerCompat.getMediaController(MediaPlayerActivity.this).unregisterCallback(controllerCallback); } mediaBrowser.disconnect(); } }
MediaBrowserCompat.ConnectionCallback anpassen
Wenn Ihre Aktivität MediaBrowserCompat erstellt, müssen Sie eine Instanz von ConnectionCallback erstellen. Ändern Sie die Methode onConnected()
, um das Mediensitzungstoken aus MediaBrowserService abzurufen, und verwenden Sie das Token, um ein MediaControllerCompat zu erstellen.
Die bequeme Methode verwenden
MediaControllerCompat.setMediaController()
um einen Link auf dem Controller zu speichern. Dies ermöglicht die Verarbeitung von Medienschaltflächen. Außerdem können Sie
MediaControllerCompat.getMediaController()
zum Abrufen des Controllers beim Erstellen der Transportsteuerungen.
Das folgende Codebeispiel zeigt, wie Sie die Methode onConnected()
ändern.
Kotlin
private val connectionCallbacks = object : MediaBrowserCompat.ConnectionCallback() { override fun onConnected() { // Get the token for the MediaSession mediaBrowser.sessionToken.also { token -> // Create a MediaControllerCompat val mediaController = MediaControllerCompat( this@MediaPlayerActivity, // Context token ) // Save the controller MediaControllerCompat.setMediaController(this@MediaPlayerActivity, mediaController) } // Finish building the UI buildTransportControls() } override fun onConnectionSuspended() { // The Service has crashed. Disable transport controls until it automatically reconnects } override fun onConnectionFailed() { // The Service has refused our connection } }
Java
private final MediaBrowserCompat.ConnectionCallback connectionCallbacks = new MediaBrowserCompat.ConnectionCallback() { @Override public void onConnected() { // Get the token for the MediaSession MediaSessionCompat.Token token = mediaBrowser.getSessionToken(); // Create a MediaControllerCompat MediaControllerCompat mediaController = new MediaControllerCompat(MediaPlayerActivity.this, // Context token); // Save the controller MediaControllerCompat.setMediaController(MediaPlayerActivity.this, mediaController); // Finish building the UI buildTransportControls(); } @Override public void onConnectionSuspended() { // The Service has crashed. Disable transport controls until it automatically reconnects } @Override public void onConnectionFailed() { // The Service has refused our connection } };
Benutzeroberfläche mit dem Media Controller verbinden
Der obige ConnectionCallback-Beispielcode enthält einen Aufruf von buildTransportControls()
zum Ausarbeiten Ihrer UI. Für die Elemente der Benutzeroberfläche, mit denen der Player gesteuert wird, müssen vorher onClickListeners eingerichtet werden. Wählen Sie die entsprechenden
MediaControllerCompat.TransportControls
-Methode hinzu.
Ihr Code sieht in etwa wie folgt aus, mit einem onClickListener für jede Schaltfläche:
Kotlin
fun buildTransportControls() { val mediaController = MediaControllerCompat.getMediaController(this@MediaPlayerActivity) // Grab the view for the play/pause button playPause = findViewById<ImageView>(R.id.play_pause).apply { setOnClickListener { // Since this is a play/pause button, you'll need to test the current state // and choose the action accordingly val pbState = mediaController.playbackState.state if (pbState == PlaybackStateCompat.STATE_PLAYING) { mediaController.transportControls.pause() } else { mediaController.transportControls.play() } } } // Display the initial state val metadata = mediaController.metadata val pbState = mediaController.playbackState // Register a Callback to stay in sync mediaController.registerCallback(controllerCallback) }
Java
void buildTransportControls() { // Grab the view for the play/pause button playPause = (ImageView) findViewById(R.id.play_pause); // Attach a listener to the button playPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Since this is a play/pause button, you'll need to test the current state // and choose the action accordingly int pbState = MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getPlaybackState().getState(); if (pbState == PlaybackStateCompat.STATE_PLAYING) { MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().pause(); } else { MediaControllerCompat.getMediaController(MediaPlayerActivity.this).getTransportControls().play(); } }); MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(MediaPlayerActivity.this); // Display the initial state MediaMetadataCompat metadata = mediaController.getMetadata(); PlaybackStateCompat pbState = mediaController.getPlaybackState(); // Register a Callback to stay in sync mediaController.registerCallback(controllerCallback); } }
Die TransportControls-Methoden senden Callbacks an die Mediensitzung Ihres Dienstes. Stellen Sie sicher, dass Sie eine entsprechende
MediaSessionCompat.Callback
-Methode für jedes Steuerelement.
Mit der Mediensitzung auf dem Laufenden bleiben
Auf der Benutzeroberfläche sollte der aktuelle Status der Mediensitzung angezeigt werden, wie durch den Wiedergabestatus und die Metadaten beschrieben. Wenn Sie die Transportsteuerungen erstellen, können Sie den aktuellen Status der Sitzung abrufen, in Ihrer UI anzeigen und die Transportsteuerelemente basierend auf dem Status und den verfügbaren Aktionen aktivieren und deaktivieren.
Um bei jeder Änderung des Status oder der Metadaten von der Mediensitzung Rückrufe zu erhalten, definieren Sie eine
MediaControllerCompat.Callback
mit diesen beiden Methoden:
Kotlin
private var controllerCallback = object : MediaControllerCompat.Callback() { override fun onMetadataChanged(metadata: MediaMetadataCompat?) {} override fun onPlaybackStateChanged(state: PlaybackStateCompat?) {} }
Java
MediaControllerCompat.Callback controllerCallback = new MediaControllerCompat.Callback() { @Override public void onMetadataChanged(MediaMetadataCompat metadata) {} @Override public void onPlaybackStateChanged(PlaybackStateCompat state) {} };
Registrieren Sie den Callback, wenn Sie die Transportsteuerungen erstellen (siehe Methode buildTransportControls()
), und heben Sie die Registrierung auf, wenn die Aktivität endet (in der onStop()
-Lebenszyklusmethode der Aktivität).
Verbindung trennen, wenn die Mediensitzung gelöscht wird
Wenn die Mediensitzung ungültig wird,
onSessionDestroyed()
-Rückrufs ausgegeben wird. In diesem Fall kann die Sitzung nicht aktiviert werden.
noch einmal innerhalb der Lebensdauer von MediaBrowserService
. Obwohl Funktionen
funktionieren möglicherweise weiterhin, ein Nutzer kann sie nicht ansehen oder steuernMediaBrowser
der Wiedergabe einer zerstörten Mediensitzung, was wahrscheinlich
den Wert der Medien beeinträchtigen wird.
Ihre Anwendung.
Wenn die Sitzung gelöscht wird, müssen Sie die Verbindung zum
MediaBrowserService
durch folgenden Anruf
disconnect()
Dadurch wird sichergestellt, dass der Browserdienst keine gebundenen Clients hat
können vom
Betriebssystem:
Wenn Sie die Verbindung zu MediaBrowserService
später wiederherstellen müssen, z. B.
Ihre App eine dauerhafte Verbindung zur Medien-App aufrechterhalten möchte,
Erstellen Sie eine neue Instanz von MediaBrowser
, anstatt die alte Instanz zu verwenden.
Das folgende Code-Snippet zeigt eine Callback-Implementierung, die wird vom Browserdienst getrennt, wenn die Mediensitzung gelöscht wird:
Kotlin
private var controllerCallback = object : MediaControllerCompat.Callback() { override fun onSessionDestroyed() { mediaBrowser.disconnect() // maybe schedule a reconnection using a new MediaBrowser instance } }
Java
MediaControllerCompat.Callback controllerCallback = new MediaControllerCompat.Callback() { @Override public void onSessionDestroyed() { mediaBrowser.disconnect(); // maybe schedule a reconnection using a new MediaBrowser instance } };