클라이언트/서버 디자인을 완료하려면 UI 코드, 연결된 MediaController 및 MediaBrowser를 포함하는 활동 구성요소를 빌드해야 합니다.
MediaBrowser에는 두 가지 중요한 기능이 있는데, 하나는 MediaBrowserService에 연결하는 것이고 다른 하나는 연결 이후 UI의 MediaController를 만드는 것입니다.
참고: MediaBrowser의 권장되는 구현은
MediaBrowserCompat
,
이는
Media-Compat 지원 라이브러리입니다.
이 페이지 전체에서 'MediaBrowser'라는 용어는 인스턴스를 의미함
(MediaBrowserCompat)
MediaBrowserService에 연결
클라이언트 활동이 생성되면 MediaBrowserService에 연결됩니다. 약간의 동작이 관련되어 있습니다. 활동의 수명 주기 콜백을 다음과 같이 수정합니다.
onCreate()
는 MediaBrowserCompat를 생성합니다. 정의한 MediaBrowserService 및 MediaBrowserCompat.ConnectionCallback의 이름을 전달하세요.onStart()
는 MediaBrowserService에 연결합니다. 여기에서 MediaBrowserCompat.ConnectionCallback이 작동합니다. 연결되면 onConnect() 콜백이 미디어 컨트롤러를 만들어 미디어 세션에 연결하고 UI 컨트롤을 MediaController에 연결하며 컨트롤러를 등록하여 미디어 세션에서 콜백을 수신합니다.onResume()
은 앱이 기기의 볼륨 컨트롤에 응답하도록 오디오 스트림을 설정합니다.onStop()
은 활동이 중지될 때 MediaBrowser의 연결을 해제하고 MediaController.Callback의 등록을 취소합니다.
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() } }
자바
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 맞춤 설정
활동에서 MediaBrowserCompat가 생성되면 ConnectionCallback의 인스턴스를 만들어야 합니다. MediaBrowserService에서 미디어 세션 토큰을 검색하고 토큰을 사용하여 MediaControllerCompat를 만들려면 onConnected()
메서드를 수정합니다.
편의 메서드 사용
MediaControllerCompat.setMediaController()
컨트롤러에 대한 링크를 저장합니다. 그러면 미디어 버튼을 처리할 수 있습니다. 또한
전송 컨트롤을 빌드할 때 컨트롤러를 검색하는 MediaControllerCompat.getMediaController()
다음 코드 샘플은 onConnected()
메서드 수정 방법을 보여줍니다.
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 } }
자바
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 } };
미디어 컨트롤러에 UI 연결
위의 ConnectionCallback 샘플 코드에는 UI를 구체화하기 위한 buildTransportControls()
호출이 포함되어 있습니다. 플레이어를 제어하는 UI 요소의 onClickListeners를 설정해야 합니다. 적절한
MediaControllerCompat.TransportControls
메서드를 사용합니다.
코드는 다음과 같으며 각 버튼에 onClickListener가 있습니다.
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) }
자바
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); } }
TransportControls 메서드는 서비스의 미디어 세션에 콜백을 보냅니다. 해당하는 광고 형식을
MediaSessionCompat.Callback
메서드를 사용해야 합니다.
미디어 세션과 동기화 유지
UI는 PlaybackState 및 Metadata에서 설명한 대로 미디어 세션의 현재 상태를 표시해야 합니다. 전송 컨트롤을 만들면 세션의 현재 상태를 가져와 UI에 표시하고, 상태 및 사용 가능한 작업에 따라 전송 컨트롤을 사용 설정 또는 사용 중지할 수 있습니다.
상태 또는 메타데이터가 변경될 때마다 미디어 세션에서 콜백을 수신하려면
MediaControllerCompat.Callback
에 다음 두 가지 메서드를 사용합니다.
Kotlin
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) {} };
전송 컨트롤을 빌드할 때 콜백을 등록하고(buildTransportControls()
메서드 참조) 활동이 중지될 때 등록을 취소합니다(활동의 onStop()
수명 주기 메서드에서).
미디어 세션 소멸 시 연결 해제
미디어 세션이 무효가 되면
onSessionDestroyed()
드림
콜백이 호출되면 이 경우 세션이 기능할 수 없습니다.
MediaBrowserService
의 전체 기간 내에 다시 호출됩니다. 함수는
MediaBrowser
관련 기능은 계속 작동할 수 있지만, 사용자는 보거나 제어할 수 없습니다.
재생 중이 아니기 때문에 손실된 미디어 세션의 가치는
실행할 수 있습니다
따라서 세션이 소멸되면 반드시
다음을 호출하여 MediaBrowserService
disconnect()
이렇게 하면 브라우저 서비스에 바인딩된 클라이언트가 없으며
인터페이스로 인해
OS를 참고하세요.
나중에 MediaBrowserService
에 다시 연결해야 하는 경우 (예:
애플리케이션이 미디어 앱과의 지속적인 연결을 유지하려고 할 때)
이전 인스턴스를 재사용하지 않고 MediaBrowser
의 새 인스턴스를 만듭니다.
다음 코드 스니펫은 다음과 같은 콜백 구현을 보여줍니다. 미디어 세션이 제거되면 브라우저 서비스에서 연결이 끊어집니다.
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 } };