برای تکمیل طراحی کارخواه/کارساز، باید مؤلفه فعالیتی بسازید که حاوی کد میانای کاربر، MediaController منسوب، و MediaBrowser باشد.
MediaBrowser دو عملکرد مهم را انجام میدهد: به MediaBrowserService متصل میشود و پساز اتصال، MediaController را برای میانای کاربر شما ایجاد میکند.
توجه: پیادهسازی توصیهشده MediaBrowser
MediaBrowserCompat است،
که در
کتابخانه پشتیبانی Media-Compat تعریف شده است.
در سراسر این صفحه، اصطلاح «MediaBrowser» به نمونهای از MediaBrowserCompat اشاره دارد.
متصل شدن به MediaBrowserService
وقتی فعالیت مشتری شما ایجاد میشود، به MediaBrowserService متصل میشود. کمی دست دادن و رقصیدن هم در کار است. فراخوانیهای چرخه حیات فعالیت را بهصورت زیر تغییر دهید:
-
onCreate()یک MediaBrowserCompat میسازد. نام MediaBrowserService و MediaBrowserCompat.ConnectionCallback را که تعریف کردهاید وارد کنید. -
onStart()به MediaBrowserService متصل میشود. اینجا جایی است که جادوی MediaBrowserCompat.ConnectionCallback وارد میشود. اگر اتصال موفقیتآمیز باشد، callback()onConnect کنترلکننده رسانه را ایجاد میکند، آن را به جلسه رسانه پیوند میدهد، کنترلهای میانای کاربر شما را به 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 } };
رابط کاربریتان را به کنترلکننده رسانه متصل کنید
در کد نمونه ConnectionCallback بالا، شامل فراخوانی به buildTransportControls() برای تکمیل واسط کاربر شما است. باید onClickListeners را برای عناصر میانای کاربر که پخشکننده را کنترل میکنند تنظیم کنید. روش 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 تماسهای برگشتی را به جلسه رسانه سرویس شما ارسال میکنند. مطمئن شوید که برای هر کنترل، روش
MediaSessionCompat.Callback متناظر را تعریف کردهاید.
با جلسه رسانه همگام بمانید
رابط کاربری باید وضعیت فعلی جلسه رسانه را، همانطور که PlaybackState و Metadata آن شرح میدهد، نمایش دهد. وقتی کنترلهای انتقال را ایجاد میکنید، میتوانید وضعیت فعلی جلسه را دریافت کنید، آن را در میانای کاربر خود نمایش دهید، و کنترلهای انتقال را براساس وضعیت و کنشهای دردسترس آن فعال و غیرفعال کنید.
برای دریافت فراخوانیهای برگشتی از جلسه رسانه هربار که وضعیت یا فراداده آن تغییر میکند، یک
MediaControllerCompat.Callback با این دو روش تعریف کنید:
کاتلین
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 ممکن است همچنان کار کنند، اما کاربر نمیتواند بازپخش را از یک جلسه رسانه تخریبشده مشاهده یا کنترل کند، که احتمالاً ارزش برنامه شما را کاهش میدهد.
بنابراین، وقتی جلسه ازبین میرود، باید با فراخوانی
disconnect()، اتصال از
MediaBrowserService را قطع کنید.
این کار تضمین میکند که سرویس مرورگر هیچ کلاینت مقیدی ندارد و
میتواند توسط
سیستمعامل ازبین برود.
اگر لازم است بعداً دوباره به 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 } };