Để hoàn tất thiết kế ứng dụng/máy chủ, bạn phải tạo thành phần hoạt động chứa mã giao diện người dùng, MediaController được liên kết và 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à sau khi kết nối, trình duyệt này sẽ tạo MediaController cho giao diện người dùng của bạn.
Lưu ý: Cách triển khai MediaBrowser được đề xuất
là MediaBrowserCompat
,
được xác định trong phần tử
Thư viện hỗ trợ Media-Compat.
Xuyên 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. Có một chút bắt tay và nhảy múa. Sửa đổi 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 là lúc sự kỳ diệu của MediaBrowserCompat.ConnectionCallback xuất hiện. 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 nghe nhìn, liên kết 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 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()
ngắt kết nối MediaBrowser và huỷ đăng ký MediaController.Callback khi hoạt động của bạn dừng.
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();
}
}
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ã thông báo phiên đa phương tiện từ MediaBrowserService và sử dụng mã thông báo để tạo MediaControllerCompat.
Sử dụng phương thức tiện lợi
MediaControllerCompat.setMediaController()
để lưu liên kết vào bộ điều khiển. Thao tác này cho phép xử lý các nút nội dung đa phương tiện. Ứng dụng này cũng cho phép bạn gọi
MediaControllerCompat.getMediaController()
để truy xuất trình điều khiển khi tạo bộ điều khiển phương tiện giao thông.
Mã mẫu sau đây cho biết cách sửa đổi phương thức onConnected()
.
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
}
};
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, bao gồm lệnh gọi đến buildTransportControls()
để bổ sung thêm cho 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 lựa chọn phù hợp
MediaControllerCompat.TransportControls
cho mỗi phần tử.
Mã của bạn sẽ trông giống như sau, với một onClickListener cho mỗi nút:
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);
}
}
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 bạn đã xác định
Phương thức MediaSessionCompat.Callback
cho từng chế độ điều khiển.
Đồng bộ hoá với phiên phát nội dung nghe nhìn
Giao diện người dùng phải cho thấy trạng thái hiện tại của phiên phát nội dung đa phương tiện, như mô tả trong PlaybackState và Metadata. Khi tạo các thành phần điều khiển phương tiện giao thông, bạn có thể lấy trạng thái hiện tại của phiên, hiển thị phiên đó trong giao diện người dùng, cũng như bật và tắt các thành phần điều khiển phương tiện giao thông dựa trên trạng thái và các hành động có sẵn.
Để nhận lệnh gọi lại từ phiên đ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:
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) {}
};
Đăng ký lệnh gọi lại khi bạn tạo các phương thức điều khiển truyền tải (xem phương thức buildTransportControls()
) và huỷ đăng ký lệnh gọi lại đó khi hoạt động dừng (trong phương thức vòng đời onStop()
của hoạt động).
Ngắt kết nối khi phiên đa phương tiện bị huỷ
Nếu phiên đa phương tiện không hợp lệ,
onSessionDestroyed()
lệnh gọi lại được phát hành. Khi điều đó xảy ra, phiên không thể hoạt động
trong vòng đời của MediaBrowserService
. Mặc dù hàm
liên quan đến MediaBrowser
có thể tiếp tục hoạt động, người dùng không thể xem hoặc kiểm soát
từ phiên phát nội dung đa phương tiện đã bị huỷ bỏ, điều này có thể làm giảm giá trị của
ứng dụng của bạn.
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 rằng dịch vụ trình duyệt không có ứng dụng khách bị ràng buộc và
có thể bị huỷ bỏ bởi
Hệ điều hành.
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),
tạo một phiên bản mới của MediaBrowser
thay vì sử dụng lại phiên bản 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 đa phương tiện bị huỷ:
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
}
};