ในการออกแบบไคลเอ็นต์/เซิร์ฟเวอร์ให้เสร็จสมบูรณ์ คุณต้องสร้างคอมโพเนนต์กิจกรรมที่มีโค้ด UI, MediaController และ MediaBrowser ที่เกี่ยวข้อง
MediaBrowser ทำหน้าที่สำคัญ 2 อย่างคือ เชื่อมต่อกับ MediaBrowserService และขณะเชื่อมต่อ ระบบจะสร้าง MediaController สำหรับ UI ของคุณ
หมายเหตุ: การใช้งาน MediaBrowser ที่แนะนำ
มีค่า MediaBrowserCompat
ซึ่งระบุไว้ใน
ไลบรารีการสนับสนุน Media-Compat
ในหน้านี้ คำว่า "MediaBrowser" อ้างอิงถึงอินสแตนซ์
MediaBrowserCompat
เชื่อมต่อกับ MediaBrowserService
เมื่อสร้างกิจกรรมของไคลเอ็นต์แล้ว กิจกรรมจะเชื่อมต่อกับ MediaBrowserService วันนี้ต้องจับมือและเต้นด้วย แก้ไข Callback วงจรของกิจกรรมดังนี้
onCreate()
สร้าง MediaBrowserCompat ส่งในชื่อ MediaBrowserService และ MediaBrowserCompat.ConnectionCallback ที่คุณกำหนดonStart()
เชื่อมต่อกับ MediaBrowserService ความพิเศษของ MediaBrowserCompat.ConnectionCallback พุ่งตรงมาตรงนี้ หากการเชื่อมต่อสำเร็จ Callback onConnect() จะสร้างตัวควบคุมสื่อ ลิงก์ตัวควบคุมกับเซสชันสื่อ ลิงก์ตัวควบคุม UI ของคุณกับ MediaController และลงทะเบียนตัวควบคุมเพื่อรับ Callback จากเซสชันสื่อonResume()
จะตั้งค่าสตรีมเสียงเพื่อให้แอปตอบสนองต่อการควบคุมระดับเสียงในอุปกรณ์onStop()
จะตัดการเชื่อมต่อ MediaBrowser และยกเลิกการลงทะเบียน MediaController.Callback เมื่อกิจกรรมของคุณหยุดลง
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 แก้ไขเมธอด onConnected()
เพื่อเรียกโทเค็นเซสชันสื่อจาก MediaBrowserService และใช้โทเค็นในการสร้าง MediaControllerCompat
ใช้วิธีการชำระเงินที่สะดวก
MediaControllerCompat.setMediaController()
เพื่อบันทึกลิงก์ไปยังตัวควบคุม การดำเนินการนี้จะเปิดใช้การจัดการปุ่มสื่อ และยังช่วยให้คุณสามารถโทร
MediaControllerCompat.getMediaController()
เพื่อเรียกข้อมูลตัวควบคุมเมื่อสร้างตัวควบคุมการขนส่ง
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีแก้ไขเมธอด 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
}
};
เชื่อมต่อ UI กับตัวควบคุมสื่อ
ในโค้ดตัวอย่างของ ConnectionCallback ข้างต้น มีการเรียก buildTransportControls()
เพื่อสร้าง UI อย่างละเอียด คุณจะต้องตั้งค่า onClickListeners สำหรับองค์ประกอบ UI ที่ควบคุมโปรแกรมเล่น เลือกตัวเลือกที่เหมาะสม
MediaControllerCompat.TransportControls
วิธีสำหรับแต่ละรายการ
โค้ดของคุณจะมีลักษณะดังนี้ โดยมี onClickListener สำหรับแต่ละปุ่ม:
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 จะส่ง Callback ไปยังเซสชันสื่อของบริการของคุณ ตรวจสอบว่าคุณได้กำหนด
MediaSessionCompat.Callback
วิธีสําหรับการควบคุมแต่ละรายการ
ติดตามเซสชันสื่ออยู่เสมอ
UI ควรแสดงสถานะปัจจุบันของเซสชันสื่อตามที่อธิบายไว้โดย PlaybackState และข้อมูลเมตา เมื่อสร้างตัวควบคุมการรับส่งข้อมูล คุณสามารถเลือกสถานะปัจจุบันของเซสชัน แสดงใน UI และเปิดและปิดใช้การควบคุมการส่งตามสถานะและการดำเนินการที่ใช้ได้
หากต้องการรับ Callback จากเซสชันสื่อทุกครั้งที่สถานะหรือข้อมูลเมตามีการเปลี่ยนแปลง ให้ระบุ
MediaControllerCompat.Callback
ได้ 2 วิธี ดังนี้
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) {}
};
ลงทะเบียน Callback เมื่อคุณสร้างตัวควบคุมการรับส่งข้อมูล (ดูเมธอด buildTransportControls()
) และยกเลิกการลงทะเบียนเมื่อกิจกรรมหยุด (ในเมธอดวงจร onStop()
ของกิจกรรม)
ยกเลิกการเชื่อมต่อเมื่อเซสชันสื่อถูกทำลาย
หากเซสชันสื่อไม่ถูกต้อง ระบบจะ
onSessionDestroyed()
มีการติดต่อกลับ เมื่อเกิดเหตุการณ์นี้ขึ้น เซสชันจะใช้งานไม่ได้
อีกครั้งตลอดอายุการใช้งานของ MediaBrowserService
แม้ว่าฟังก์ชัน
ที่เกี่ยวข้องกับ MediaBrowser
อาจทำงานต่อไป ผู้ใช้ดูหรือควบคุมไม่ได้
การเล่นจากเซสชันสื่อที่ถูกทำลาย ซึ่งมีแนวโน้มที่จะลดค่าของ
แอปพลิเคชันของคุณ
ดังนั้น เมื่อเซสชันถูกทำลาย คุณต้องยกเลิกการเชื่อมต่อจาก
MediaBrowserService
โดยการโทร
disconnect()
ซึ่งทำให้มั่นใจได้ว่าบริการเบราว์เซอร์ไม่มีไคลเอ็นต์ที่ผูกกับไคลเอ็นต์และ
สามารถถูกทำลายได้ด้วย
OS
หากคุณต้องการเชื่อมต่อกับ MediaBrowserService
อีกครั้งในภายหลัง (ตัวอย่างเช่น หาก
แอปพลิเคชันของคุณต้องการรักษาการเชื่อมต่อกับแอปสื่อตลอดเวลา)
สร้างอินสแตนซ์ ใหม่ ของ MediaBrowser
แทนที่จะใช้อันเก่าซ้ำ
ข้อมูลโค้ดต่อไปนี้แสดงการใช้งาน Callback ที่ ยกเลิกการเชื่อมต่อจากบริการเบราว์เซอร์เมื่อเซสชันสื่อถูกทำลาย:
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
}
};