Medienbrowser-Client erstellen

Um das Client/Server-Design abzuschließen, müssen Sie eine Aktivitätskomponente erstellen, die Ihren UI-Code, einen verknüpften 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 der Verbindung den MediaController für Ihre Benutzeroberfläche.

Hinweis : Die empfohlene Implementierung von MediaBrowser ist MediaBrowserCompat, die in der Media-Compat-Supportbibliothek definiert ist. Auf dieser Seite bezieht sich der Begriff „MediaBrowser“ auf eine Instanz von MediaBrowserCompat.

Verbindung zu MediaBrowserService herstellen

Wenn Ihre Clientaktivität erstellt wurde, wird eine Verbindung zum MediaBrowserService hergestellt. Es geht um Handschlag und Tanz. Ändern Sie die Lebenszyklus-Callbacks der Aktivität so:

  • onCreate() erstellt ein MediaBrowserCompat. Übergeben Sie den Namen Ihres MediaBrowserService und den von Ihnen definierten MediaBrowserCompat.ConnectionCallback.
  • onStart() stellt eine Verbindung zum MediaBrowserService her. Hier kommt die Magie von MediaBrowserCompat.ConnectionCallback ins Spiel. Wenn die Verbindung erfolgreich hergestellt wird, erstellt der onConnect()-Callback den Medien-Controller, verknüpft ihn mit der Mediensitzung, verknüpft Ihre UI-Steuerelemente mit MediaController und registriert den Controller für den Empfang von Callbacks von der Mediensitzung.
  • onResume() legt den Audiostream so fest, dass deine App auf die Lautstärkeregelung des Geräts reagiert.
  • onStop() trennt Ihren MediaBrowser und hebt die Registrierung von MediaController.Callback auf, wenn Ihre 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 dem MediaBrowserService abzurufen, und verwenden Sie das Token, um ein MediaControllerCompat zu erstellen.

Verwenden Sie die praktische Methode MediaControllerCompat.setMediaController(), um einen Link zum Controller zu speichern. Dadurch können Medienschaltflächen verarbeitet werden. Außerdem können Sie MediaControllerCompat.getMediaController() aufrufen, um den Controller beim Erstellen der Transportsteuerungen abzurufen.

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 der Mediensteuerung verbinden

Der obige ConnectionCallback-Beispielcode enthält einen Aufruf von buildTransportControls(), um Ihre UI zu vervollständigen. Für die UI-Elemente, die den Player steuern, ist die Einrichtung von QuickListenern erforderlich. Wählen Sie jeweils die geeignete MediaControllerCompat.TransportControls-Methode aus.

Ihr Code sieht ungefähr so aus, wobei für jede Schaltfläche ein Istio-Listener vorhanden ist:

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. Für jedes Steuerelement muss eine entsprechende MediaSessionCompat.Callback-Methode definiert sein.

Immer auf dem neuesten Stand

Auf der Benutzeroberfläche sollte der aktuelle Status der Mediensitzung angezeigt werden, wie durch den Wiedergabestatus und die Metadaten beschrieben. Wenn Sie die Transportsteuerung erstellen, können Sie den aktuellen Status der Sitzung abrufen, ihn auf Ihrer UI anzeigen lassen und Transportsteuerungen basierend auf dem Status und seinen verfügbaren Aktionen aktivieren und deaktivieren.

Wenn Sie bei jeder Änderung des Status oder der Metadaten Callbacks von der Mediensitzung erhalten möchten, definieren Sie mit den folgenden beiden Methoden eine MediaControllerCompat.Callback:

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 Transportsteuerelemente erstellen (siehe Methode buildTransportControls()) und heben Sie die Registrierung auf, wenn die Aktivität beendet wird (in der Lebenszyklusmethode onStop() der Aktivität).

Verbindung trennen, wenn die Mediensitzung gelöscht wird

Wenn die Mediensitzung ungültig wird, wird der onSessionDestroyed()-Callback ausgegeben. In diesem Fall kann die Sitzung innerhalb der Lebensdauer von MediaBrowserService nicht wieder funktionsfähig werden. Funktionen im Zusammenhang mit MediaBrowser funktionieren möglicherweise weiterhin. Ein Nutzer kann die Wiedergabe einer gelöschten Mediensitzung jedoch nicht sehen oder steuern. Dies wird wahrscheinlich den Wert Ihrer Anwendung beeinträchtigen.

Wenn die Sitzung gelöscht wird, müssen Sie daher die Verbindung zur MediaBrowserService trennen, indem Sie disconnect() aufrufen. Dadurch wird sichergestellt, dass der Browserdienst keine gebundenen Clients hat und vom Betriebssystem gelöscht werden kann. Wenn Sie die Verbindung zu MediaBrowserService später wiederherstellen müssen, z. B. wenn Ihre Anwendung eine persistente Verbindung zur Medienanwendung aufrechterhalten möchte, erstellen Sie eine neue Instanz von MediaBrowser, anstatt die alte Instanz zu verwenden.

Das folgende Code-Snippet zeigt eine Callback-Implementierung, bei der die Verbindung zum Browserdienst getrennt wird, 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
    }
  };