آغاز به کار با CastPlayer

CastPlayer پیاده‌سازی پخش‌کننده Jetpack Media3 است که از هم بازپخش محلی و هم پخش محتوا در دستگاه سازگار با Cast ازراه‌دور پشتیبانی می‌کند. CastPlayer افزودن عملکرد پخش محتوا را به برنامه‌تان ساده می‌کند و ویژگی‌های غنی‌ای برای جابه‌جایی یکپارچه بین بازپخش محلی و از دور ارائه می‌دهد. این راهنما نحوه ادغام CastPlayer در برنامه رسانه‌ای شما را نشان می‌دهد.

برای ادغام کردن Cast با پلاتفرم‌های دیگر، کیت توسعه نرم‌افزار Cast را ببینید.

دریافت دستگاه سازگار با Cast

برای آزمایش CastPlayer، به دستگاه سازگار با Cast نیاز دارید. گزینه‌ها شامل Android TV،‏ Chromecast، بلندگوهای هوشمند، و نمایشگرهای هوشمند می‌شود. تأیید کنید که دستگاهتان راه‌اندازی شده باشد و برای شناسایی به همان شبکه Wi-Fi متصل باشد که تلفن همراه توسعه‌دهنده به آن متصل است.

افزودن وابستگی‌های ساخت

برای شروع استفاده از CastPlayer، وابستگی‌های AndroidX Media3 و CastPlayer را به فایل build.gradle واحد برنامه خود اضافه کنید.

کاتلین

implementation("androidx.media3:media3-exoplayer:1.11.1")
implementation("androidx.media3:media3-ui:1.11.1")
implementation("androidx.media3:media3-session:1.11.1")
implementation("androidx.media3:media3-cast:1.11.1")

شیک

implementation "androidx.media3:media3-exoplayer:1.11.1"
implementation "androidx.media3:media3-ui:1.11.1"
implementation "androidx.media3:media3-session:1.11.1"
implementation "androidx.media3:media3-cast:1.11.1"

پیکربندی CastPlayer

برای پیکربندی CastPlayer، فایل AndroidManifest.xml خود را با ارائه‌دهنده گزینه‌ها به‌روز کنید.

ارائه‌دهنده گزینه‌ها

‫CastPlayer برای پیکربندی عملکردش به ارائه‌دهنده گزینه‌ها نیاز دارد. برای راه‌اندازی پایه، می‌توانید با افزودن DefaultCastOptionsProvider به فایل AndroidManifest.xml از آن استفاده کنید. این کار از تنظیمات پیش‌فرض، ازجمله برنامه گیرنده پیش‌فرض، استفاده می‌کند.

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
    android:value="androidx.media3.cast.DefaultCastOptionsProvider" />
  ...
</application>

برای سفارشی‌سازی پیکربندی، OptionsProvider سفارشی خودتان را پیاده‌سازی کنید. برای آشنایی با نحوه انجام این کار، به راهنمای CastOptions مراجعه کنید.

گیرنده‌ای برای انتقال رسانه اضافه کنید

افزودن MediaTransferReceiver به مانیفست باعث می‌شود «میانای کاربر سیستم» بتواند دستگاه‌های سازگار با Cast را در شبکه پیدا کند و رسانه را بدون باز کردن فعالیت برنامه مسیریابی مجدد کند. برای مثال، کاربر می‌تواند دستگاه پخش‌کننده رسانه برنامه شما را از اعلان رسانه تغییر دهد.

<application>
  ...
  <receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
  ...
</application>

ساختن CastPlayer

برای پخش محتوای از دور با Cast، برنامه شما باید بتواند پخش را حتی زمانی که کاربر با «فعالیتی» از برنامه شما تعامل ندارد (مثلاً ازطریق اعلان رسانه سیستم) مدیریت کند. به همین دلیل، باید نمونه‌های ExoPlayer (برای بازپخش محلی) و CastPlayer (برای بازپخش از دور) را در سرویسی مثل MediaSessionService یا MediaLibraryService ایجاد کنید. ابتدا نمونه ExoPlayer خود را ایجاد کنید و سپس هنگام ساختن نمونه CastPlayer، ExoPlayer را به‌عنوان نمونه پخش‌کننده محلی تنظیم کنید. سپس می‌توانید پخش رسانه را بین تلفن همراه و دستگاه سازگار با «پخش محتوا» از اعلان رسانه یا اعلان صفحه قفل جابه‌جا کنید. ‫Media3 از ویژگی Output Switcher برای مدیریت انتقال پخش‌کننده هنگام تغییر مسیر برونداد از محلی به از دور یا از از دور به محلی استفاده می‌کند.

نماگرفتی که میانای کاربر «تعویض‌کننده برونداد» را در اعلان‌ها نشان می‌دهد.
شکل ۱: (الف) تراشه دستگاه در اعلان «رسانه» (ب) دستگاه‌های دارای قابلیت «پخش محتوا» که با تک‌ضرب زدن روی تراشه دستگاه نشان داده می‌شوند (ج) تراشه دستگاه در اعلان «صفحه قفل»

کاتلین

override fun onCreate() {
  super.onCreate()

  val exoPlayer = ExoPlayer.Builder(context).build()
  val castPlayer = CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build()

  mediaSession = MediaSession.Builder(context, castPlayer).build()
}

جاوا

@Override
public void onCreate() {
  super.onCreate();

  ExoPlayer exoPlayer = new ExoPlayer.Builder(context).build();
  CastPlayer castPlayer = new CastPlayer.Builder(context).setLocalPlayer(exoPlayer).build();

  mediaSession =
      new MediaSession.Builder(/* context= */ context, /* player= */ castPlayer).build();
}

افزودن عناصر میانای کاربر

MediaRouteButton را به واسط کاربر برنامه‌تان اضافه کنید. با تک‌ضرب زدن روی MediaRouteButton کادر گفتگویی باز می‌شود که فهرستی از دستگاه‌های سازگار با Cast دردسترس در شبکه را نمایش می‌دهد. وقتی کاربر دستگاهی را انتخاب می‌کند، بازپخش رسانه از تلفن همراه به دستگاه گیرنده انتخابی منتقل می‌شود. این بخش نحوه افزودن دکمه و گوش دادن به رویدادها را برای به‌روزرسانی واسط کاربر هنگام تغییر بازپخش بین دستگاه‌های محلی و از دور نشان می‌دهد.

تنظیم MediaRouteButton

چهار روش برای افزودن MediaRouteButton به واسط کاربر فعالیتتان وجود دارد. بهترین انتخاب به طراحی و الزامات برنامه شما بستگی دارد.

  • میانای کاربر Compose: یک عنصر ترکیبی دکمه اضافه کنید.
  • نمای واسط کاربر:
    • دکمه را به منو نوار برنامه اضافه کنید.
    • دکمه را در PlayerView اضافه کنید.
    • دکمه را به‌عنوان View استاندارد اضافه کنید.
نماگرفتی که «دکمه مسیر رسانه» را در واسط کاربر نشان می‌دهد.
شکل ۲: (الف) MediaRouteButton در نوار منو، (ب) به‌عنوان View، (ج) در PlayerView، و (د) کادر گفتگوی دستگاه‌های سازگار با Cast.

افزودن عنصر ترکیبی MediaRouteButton به «پخش‌کننده»

می‌توانید MediaRouteButton Composable را به واسط کاربر پخش‌کننده خود اضافه کنید. برای اطلاعات بیشتر، راهنمای نوشتن را ببینید.

@Composable
fun PlayerComposeView(player: Player, modifier: Modifier = Modifier) {
  var controlsVisible by remember { mutableStateOf(false) }

  Box(
    modifier = modifier.clickable { controlsVisible = true },
    contentAlignment = Alignment.Center,
  ) {
    PlayerSurface(player = player, modifier = modifier)
    AnimatedVisibility(visible = controlsVisible, enter = fadeIn(), exit = fadeOut()) {
      Box(modifier = Modifier.fillMaxSize()) {
        MediaRouteButton(modifier = Modifier.align(Alignment.TopEnd))
        PrimaryControls(player = player, modifier = Modifier.align(Alignment.Center))
      }
    }
  }
}

@Composable
fun PrimaryControls(player: Player, modifier: Modifier = Modifier) {
  // ...
}

‫MediaRouteButton را به PlayerView اضافه کنید

می‌توانید MediaRouteButton را مستقیماً در کنترل‌های رابط کاربری PlayerView اضافه کنید. پس‌از تنظیم MediaController به‌عنوان پخش‌کننده برای PlayerView، MediaRouteButtonViewProvider را برای نمایش دکمه «پخش محتوا» در «پخش‌کننده» ارائه دهید.

کاتلین

override fun onStart() {
  super.onStart()

  playerView.player = mediaController
  playerView.setMediaRouteButtonViewProvider(MediaRouteButtonViewProvider())
}

جاوا

@Override
public void onStart() {
  super.onStart();

  playerView.setPlayer(mediaController);
  playerView.setMediaRouteButtonViewProvider(new MediaRouteButtonViewProvider());
}

‫MediaRouteButton را به منو نوار برنامه اضافه کنید

برای راه‌اندازی MediaRouteButton در منو نوار برنامه، منو XML ایجاد کنید و onCreateOptionsMenu را در Activity خود ملغی کنید.

<menu xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:app="http://schemas.android.com/apk/res-auto">
  <item android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:showAsAction="always"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"/>
</menu>

کاتلین

override fun onCreateOptionsMenu(menu: Menu): Boolean {
  // ...
  menuInflater.inflate(R.menu.sample_media_route_button_menu, menu)
  val menuItemFuture: ListenableFuture<MenuItem> =
    MediaRouteButtonFactory.setUpMediaRouteButton(context, menu, R.id.media_route_menu_item)
  Futures.addCallback(
    menuItemFuture,
    object : FutureCallback<MenuItem> {
      override fun onSuccess(menuItem: MenuItem?) {
        // Do something with the menu item.
      }

      override fun onFailure(t: Throwable) {
        // Handle the failure.
      }
    },
    executor,
  )
  // ...
  return true
}

جاوا

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // ...
  getMenuInflater().inflate(R.menu.sample_media_route_button_menu, menu);
  ListenableFuture<MenuItem> menuItemFuture =
      MediaRouteButtonFactory.setUpMediaRouteButton(context, menu, R.id.media_route_menu_item);
  Futures.addCallback(
      menuItemFuture,
      new FutureCallback<MenuItem>() {
        @Override
        public void onSuccess(MenuItem menuItem) {
          // Do something with the menu item.
        }

        @Override
        public void onFailure(Throwable t) {
          // Handle the failure.
        }
      },
      executor);
  // ...
  return true;
}

افزودن MediaRouteButton به‌عنوان «نما»

می‌توانید MediaRouteButton را در activity layout.xml راه‌اندازی کنید.

  <androidx.mediarouter.app.MediaRouteButton
      android:id="@+id/media_route_button"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:mediaRouteButtonTint="@android:color/white" />

برای تکمیل راه‌اندازی MediaRouteButton، از Media3 Cast MediaRouteButtonFactory در کد Activity خود استفاده کنید.

کاتلین

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  findViewById<MediaRouteButton>(R.id.media_route_button)?.also {
    val unused = MediaRouteButtonFactory.setUpMediaRouteButton(context, it)
  }
}

جاوا

@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  // ...
  MediaRouteButton button = findViewById(R.id.media_route_button);
  ListenableFuture<Void> setUpFuture =
      MediaRouteButtonFactory.setUpMediaRouteButton(context, button);
}

شنونده فعالیت

Player.Listener را در Activity خود ایجاد کنید تا به تغییرات مکان بازپخش رسانه گوش دهد. وقتی playbackType بین PLAYBACK_TYPE_LOCAL و PLAYBACK_TYPE_REMOTE تغییر می‌کند، می‌توانید واسط کاربر را درصورت نیاز تنظیم کنید. برای جلوگیری از نشت حافظه و محدود کردن فعالیت شنونده به زمانی که برنامه شما نمایان است، شنونده را در onStart ثبت کنید و آن را در onStop لغو ثبت کنید:

کاتلین

private val playerListener: Player.Listener =
  object : Player.Listener {
    override fun onDeviceInfoChanged(deviceInfo: DeviceInfo) {
      if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
        // Add UI changes for local playback.
      } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
        // Add UI changes for remote playback.
      }
    }
  }

override fun onStart() {
  super.onStart()
  mediaController.addListener(playerListener)
}

override fun onStop() {
  super.onStop()
  mediaController.removeListener(playerListener)
}

جاوا

private final Player.Listener playerListener =
    new Player.Listener() {
      @Override
      public void onDeviceInfoChanged(DeviceInfo deviceInfo) {
        if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_LOCAL) {
          // Add UI changes for local playback.
        } else if (deviceInfo.playbackType == DeviceInfo.PLAYBACK_TYPE_REMOTE) {
          // Add UI changes for remote playback.
        }
      }
    };

@Override
protected void onStart() {
  super.onStart();
  mediaController.addListener(playerListener);
}

@Override
protected void onStop() {
  super.onStop();
  mediaController.removeListener(playerListener);
}

برای کسب اطلاعات بیشتر درباره گوش دادن و پاسخ دادن به رویدادهای بازپخش، راهنمای رویدادهای پخش‌کننده را ببینید.