برای تکمیل طراحی کلاینت/سرور، باید یک جزء Activity بسازید که حاوی کد UI شما، یک MediaController مرتبط و یک MediaBrowser باشد.
MediaBrowser دو عملکرد مهم را انجام می دهد: به MediaBrowserService متصل می شود و پس از اتصال 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 میشود.
کاتلین
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
ایجاد کنید.
قطعه کد زیر اجرای فراخوانی را نشان می دهد که با از بین رفتن جلسه رسانه از سرویس مرورگر قطع می شود:
کاتلین
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 } };