Để hoàn tất thiết kế ứng dụng/máy chủ, bạn phải tạo một thành phần hoạt động chứa mã giao diện người dùng, một MediaController được liên kết và một MediaBrowser.
MediaBrowser thực hiện hai chức năng quan trọng: Trình duyệt này kết nối với MediaBrowserService và khi kết nối sẽ tạo MediaController cho giao diện người dùng của bạn.
Lưu ý: Bạn nên triển khai MediaBrowser là MediaBrowserCompat
, được xác định trong thư viện hỗ trợ Media-Compat.
Trong suốt trang này, thuật ngữ "MediaBrowser" đề cập đến một thực thể của MediaBrowserCompat.
Kết nối với MediaBrowserService
Khi hoạt động của ứng dụng được tạo, hoạt động đó sẽ kết nối với MediaBrowserService. Tôi có một vài cái bắt tay và một điệu nhảy. Sửa đổi các phương thức gọi lại trong vòng đời của hoạt động như sau:
onCreate()
tạo MediaBrowserCompat. Truyền tên của MediaBrowserService và MediaBrowserCompat.ConnectionCallback mà bạn đã xác định.onStart()
kết nối với MediaBrowserService. Đây chính là lúc sự kỳ diệu của MediaBrowserCompat.ConnectionCallback phát huy tác dụng. Nếu kết nối thành công, lệnh gọi lại onConnect() sẽ tạo trình điều khiển nội dung đa phương tiện, liên kết trình điều khiển đó với phiên phát nội dung đa phương tiện, liên kết các chế độ điều khiển trên giao diện người dùng của bạn với MediaController và đăng ký trình điều khiển để nhận lệnh gọi lại từ phiên phát nội dung đa phương tiện.onResume()
thiết lập luồng âm thanh để ứng dụng của bạn phản hồi chế độ điều chỉnh âm lượng trên thiết bị.onStop()
sẽ ngắt kết nối MediaBrowser và huỷ đăng ký MediaController.Callback khi hoạt động của bạn dừng.
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(); } }
Tuỳ chỉnh MediaBrowserCompat.ConnectionCallback
Khi hoạt động của bạn tạo MediaBrowserCompat, bạn phải tạo một thực thể của ConnectionCallback. Sửa đổi phương thức onConnected()
để truy xuất mã phiên phát nội dung đa phương tiện từ MediaBrowserService và sử dụng mã thông báo này để tạo MediaControllerCompat.
Sử dụng phương thức tiện lợi MediaControllerCompat.setMediaController()
để lưu đường liên kết vào tay điều khiển. Trường này cho phép xử lý các nút nội dung đa phương tiện. API này cũng cho phép bạn gọi MediaControllerCompat.getMediaController()
để truy xuất bộ điều khiển khi tạo bộ điều khiển truyền tải.
Mã mẫu sau đây cho biết cách sửa đổi phương thức 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 } }
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 } };
Kết nối giao diện người dùng với trình điều khiển nội dung nghe nhìn
Trong mã mẫu ConnectionCallback ở trên, hãy đưa lệnh gọi đến buildTransportControls()
để hoàn thiện giao diện người dùng của bạn. Bạn cần đặt onClickListener cho các phần tử trên giao diện người dùng điều khiển trình phát. Chọn phương thức MediaControllerCompat.TransportControls
thích hợp cho từng phương thức.
Mã của bạn sẽ trông giống như sau, với một onClickListener cho mỗi nút:
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); } }
Các phương thức TransportControls sẽ gửi lệnh gọi lại đến phiên phát nội dung đa phương tiện của dịch vụ. Hãy đảm bảo rằng bạn đã xác định phương thức MediaSessionCompat.Callback
tương ứng cho từng chế độ điều khiển.
Đồng bộ hoá phiên phát nội dung đa phương tiện
Giao diện người dùng phải hiển thị trạng thái hiện tại của phiên phát nội dung đa phương tiện, như được mô tả trong PlaybackState và Siêu dữ liệu. Khi tạo các chế độ điều khiển truyền tải, bạn có thể lấy trạng thái hiện tại của phiên hoạt động, hiển thị trạng thái đó trong giao diện người dùng, cũng như bật và tắt các chế độ điều khiển truyền tải dựa trên trạng thái và các thao tác hiện có.
Để nhận lệnh gọi lại từ phiên phát nội dung đa phương tiện mỗi khi trạng thái hoặc siêu dữ liệu của phiên đó thay đổi, hãy xác định MediaControllerCompat.Callback
bằng 2 phương thức sau:
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) {} };
Đăng ký lệnh gọi lại khi bạn tạo các điều khiển truyền tải (xem phương thức buildTransportControls()
) và huỷ đăng ký khi hoạt động ngừng hoạt động (trong phương thức vòng đời onStop()
của hoạt động).
Ngắt kết nối khi phiên phát nội dung đa phương tiện bị huỷ
Nếu phiên phát nội dung đa phương tiện không hợp lệ, lệnh gọi lại onSessionDestroyed()
sẽ được đưa ra. Khi điều đó xảy ra, phiên đó không thể hoạt động trở lại trong vòng đời của MediaBrowserService
. Mặc dù các hàm liên quan đến MediaBrowser
có thể tiếp tục hoạt động, nhưng người dùng không thể xem hoặc kiểm soát việc phát từ một phiên nội dung nghe nhìn bị huỷ bỏ. Điều này có thể làm giảm giá trị của ứng dụng.
Do đó, khi phiên bị huỷ, bạn phải ngắt kết nối khỏi MediaBrowserService
bằng cách gọi disconnect()
.
Điều này đảm bảo dịch vụ trình duyệt không có ứng dụng liên kết và hệ điều hành có thể huỷ.
Nếu sau này bạn cần kết nối lại với MediaBrowserService
(ví dụ: nếu ứng dụng của bạn muốn duy trì kết nối liên tục với ứng dụng đa phương tiện), hãy tạo một thực thể MediaBrowser
mới thay vì sử dụng lại thực thể cũ.
Đoạn mã sau đây minh hoạ cách triển khai lệnh gọi lại ngắt kết nối khỏi dịch vụ trình duyệt khi phiên phát nội dung đa phương tiện bị huỷ:
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 } };