ساخت مشتری مرورگر رسانه

برای تکمیل طراحی کلاینت/سرور، باید یک جزء 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
    }
  };