Tworzenie klienta przeglądarki multimediów

Aby zakończyć projekt klienta/serwer, musisz utworzyć komponent aktywności zawierający kod interfejsu, powiązany element MediaController i Media Browser.

Przeglądarka Media Browser wykonuje dwie ważne funkcje: łączy się z usługą Media BrowserService, a po jej podłączeniu tworzy element MediaController dla interfejsu użytkownika.

Uwaga: zalecana implementacja Media Browser to MediaBrowserCompat, , która jest definiowana w Biblioteka pomocy Media-Compat. Na tej stronie określenie „Media Browser” odnosi się do instancji w Media BrowserCompat.

Łączenie się z usługą Media BrowserService

Gdy aktywność klienta jest tworzona, łączy się z usługą Media BrowserService. Wystarczy uścisk dłoni i taniec. Zmodyfikuj wywołania zwrotne cyklu życia aktywności w ten sposób:

  • onCreate() tworzy obiekt Media BrowserCompat. Przekaż nazwę usługi Media BrowserService i zdefiniowaną przez siebie nazwę Media BrowserCompat.ConnectionCallback.
  • onStart() łączy się z usługą Media BrowserService. Właśnie tu do akcji wkracza magia Media BrowserCompat.ConnectionCallback. Jeśli połączenie się powiedzie, wywołanie zwrotne onConnect() utworzy kontroler multimediów, łączy go z sesją multimediów, łączy elementy sterujące interfejsu z kontrolerem MediaController i rejestruje kontroler, aby odbierał wywołania zwrotne z sesji multimediów.
  • onResume() ustawia strumień audio w taki sposób, aby aplikacja reagowała na sterowanie głośnością urządzenia.
  • onStop() odłącza przeglądarkę Media Browser i wyrejestruje kontrolera MediaController.Callback po zatrzymaniu aktywności.
KotlinJava
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()
   
}
}
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();

 
}
}

Dostosuj Media BrowserCompat.ConnectionCallback

Gdy aktywność tworzy Media BrowserCompat, musisz utworzyć instancję ConnectionCallback. Zmodyfikuj swoją metodę onConnected(), aby pobrać token sesji multimediów z usługi Media BrowserService i użyj go do utworzenia obiektu MediaControllerCompat.

Korzystanie z metody zapewniającej wygodę MediaControllerCompat.setMediaController() aby zapisać połączenie z kontrolerem. Umożliwia obsługę przycisków multimediów. Pozwala też dzwonić MediaControllerCompat.getMediaController(), aby pobrać kontroler podczas tworzenia elementów sterujących transportem.

Poniższy przykładowy kod pokazuje, jak zmodyfikować metodę onConnected().

KotlinJava
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
   
}
}
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
   
}
 
};

Połącz interfejs użytkownika z kontrolerem multimediów

W przykładowym kodzie ConnectionCallback powyżej znajduje się wywołanie buildTransportControls() w celu dopracowania interfejsu użytkownika. Musisz ustawić onClickListeners dla elementów interfejsu, które sterują odtwarzaczem. Wybierz odpowiednią Metoda MediaControllerCompat.TransportControls dla każdej z nich.

Kod będzie wyglądał mniej więcej tak, z instancją onClickListener dla każdego przycisku:

KotlinJava
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)
}
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);
}
}

Metody TransportControls wysyłają wywołania zwrotne do sesji multimediów Twojej usługi. Upewnij się, że zdefiniujesz tag Metoda MediaSessionCompat.Callback dla każdego elementu sterującego.

Bądź na bieżąco z sesją multimediów

Interfejs powinien wyświetlać bieżący stan sesji multimedialnej zgodnie z opisem w parametrach OdtwarzanieState i Metadane. Po utworzeniu elementów sterujących transportem możesz pobrać bieżący stan sesji, wyświetlić go w interfejsie i włączyć lub wyłączyć elementy sterujące transportem na podstawie stanu i dostępnych działań.

Aby otrzymywać wywołania zwrotne z sesji multimediów po każdej zmianie jej stanu lub metadanych, zdefiniuj MediaControllerCompat.Callback, korzystając z tych 2 metod:

KotlinJava
private var controllerCallback = object : MediaControllerCompat.Callback() {

   
override fun onMetadataChanged(metadata: MediaMetadataCompat?) {}

   
override fun onPlaybackStateChanged(state: PlaybackStateCompat?) {}
}
MediaControllerCompat.Callback controllerCallback =
 
new MediaControllerCompat.Callback() {
   
@Override
   
public void onMetadataChanged(MediaMetadataCompat metadata) {}

   
@Override
   
public void onPlaybackStateChanged(PlaybackStateCompat state) {}
 
};

Zarejestruj wywołanie zwrotne podczas tworzenia elementów sterujących transportu (zobacz metodę buildTransportControls()) i wyrejestruj je po zatrzymaniu działania (w metodzie cyklu życia onStop() aktywności).

Rozłącz po zniszczeniu sesji multimediów

Jeśli sesja multimediów stanie się nieprawidłowa, parametr onSessionDestroyed() wywołanie zwrotne. W takim przypadku sesja nie może stać się funkcjonalna. jeszcze raz w okresie MediaBrowserService. Chociaż funkcje związane z MediaBrowser mogą nadal działać, użytkownik nie może wyświetlać ani kontrolować odtwarzania z zniszczonej sesji multimediów, co prawdopodobnie zmniejsza wartość Twojej aplikacji.

Dlatego po zniszczeniu sesji musisz odłączyć się od MediaBrowserService przez połączenie disconnect() Dzięki temu usługa przeglądarki nie będzie mieć powiązanych klientów może zostać zniszczona przez Jeśli chcesz później ponownie połączyć się z urządzeniem MediaBrowserService (na przykład aplikacja chce utrzymać trwałe połączenie z aplikacją do multimediów), utwórz nową instancję MediaBrowser, zamiast używać starej.

Fragment kodu poniżej przedstawia implementację wywołania zwrotnego, rozłącza się z usługą przeglądarki w chwili zniszczenia sesji multimediów:

KotlinJava
private var controllerCallback = object : MediaControllerCompat.Callback() {
   
override fun onSessionDestroyed() {
      mediaBrowser
.disconnect()
     
// maybe schedule a reconnection using a new MediaBrowser instance
   
}
}
MediaControllerCompat.Callback controllerCallback =
 
new MediaControllerCompat.Callback() {
   
@Override
   
public void onSessionDestroyed() {
      mediaBrowser
.disconnect();
     
// maybe schedule a reconnection using a new MediaBrowser instance
   
}
 
};