การเริ่มต้นใช้งาน CastPlayer

CastPlayer เป็นการติดตั้งใช้งาน Player ของ Jetpack Media3 ที่รองรับ ทั้งการเล่นในเครื่องและการแคสต์ไปยังอุปกรณ์ระยะไกลที่พร้อมใช้งาน Cast CastPlayer ช่วยให้การเพิ่มฟังก์ชันการแคสต์ลงในแอปเป็นเรื่องง่ายและมีฟีเจอร์มากมายที่ช่วยให้ สลับระหว่างการเล่นในเครื่องและการเล่นจากระยะไกลได้อย่างราบรื่น คู่มือนี้แสดงวิธี ผสานรวม CastPlayer เข้ากับแอปสื่อ

หากต้องการผสานรวม Cast กับแพลตฟอร์มอื่นๆ โปรดดู Cast SDK

ซื้ออุปกรณ์ที่พร้อมใช้งาน Cast

หากต้องการทดสอบ CastPlayer คุณต้องมีอุปกรณ์ที่พร้อมใช้งาน Cast โดยมีตัวเลือก ได้แก่ Android TV, Chromecast, ลำโพงอัจฉริยะ และจอแสดงผลอัจฉริยะ ตรวจสอบว่าอุปกรณ์ ตั้งค่าและเชื่อมต่อกับเครือข่าย Wi-Fi เดียวกันกับอุปกรณ์เคลื่อนที่ที่ใช้พัฒนาสำหรับการ ค้นพบ

เพิ่มการพึ่งพิงบิวด์

หากต้องการเริ่มใช้ CastPlayer ให้เพิ่มการอ้างอิง AndroidX Media3 และ CastPlayer ลงในไฟล์ build.gradle ของโมดูลแอป

Kotlin

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

Groovy

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

กำหนดค่า 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 ลงในไฟล์ Manifest จะช่วยให้ UI ของระบบ ค้นพบอุปกรณ์ที่พร้อมใช้งาน Cast ในเครือข่ายและเปลี่ยนเส้นทางสื่อได้โดยไม่ต้องเปิด กิจกรรมของแอป เช่น ผู้ใช้สามารถเปลี่ยนอุปกรณ์ที่เล่นสื่อของแอปได้จากการแจ้งเตือนสื่อ

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

สร้าง CastPlayer

สำหรับการเล่นจากระยะไกลด้วย Cast แอปควรจัดการการเล่นได้แม้ว่าผู้ใช้จะไม่ได้โต้ตอบกับกิจกรรมจากแอป เช่น ผ่านการแจ้งเตือนสื่อของระบบ ด้วยเหตุนี้ คุณจึงควรสร้างอินสแตนซ์ ExoPlayer (สำหรับการเล่นในเครื่อง) และ CastPlayer (สำหรับการเล่นจากระยะไกล) ในบริการ เช่น MediaSessionService หรือ MediaLibraryService ก่อนอื่น ให้สร้างอินสแตนซ์ ExoPlayer แล้วเมื่อสร้างอินสแตนซ์ CastPlayer ให้ตั้งค่า ExoPlayer เป็นอินสแตนซ์เครื่องเล่นในเครื่อง จากนั้นคุณจะสลับการเล่นสื่อระหว่างอุปกรณ์เคลื่อนที่กับอุปกรณ์ที่พร้อมใช้งาน Cast ได้จากการแจ้งเตือนสื่อหรือการแจ้งเตือนบนหน้าจอล็อก Media3 ใช้ฟีเจอร์Output Switcher เพื่อจัดการการโอนเพลเยอร์เมื่อเส้นทางการส่งออกเปลี่ยนจาก ภายในเป็นระยะไกล หรือจากระยะไกลเป็นภายใน

ภาพหน้าจอแสดง UI ตัวสลับเอาต์พุตในการแจ้งเตือน
รูปที่ 1: (ก) ชิปอุปกรณ์ในการแจ้งเตือนสื่อ (ข) อุปกรณ์ที่พร้อมแคสต์ซึ่งแสดงเมื่อแตะชิปอุปกรณ์ (ค) ชิปอุปกรณ์ในการแจ้งเตือนบนหน้าจอล็อก

Kotlin

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()
}

Java

@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();
}

เพิ่มองค์ประกอบ UI

เพิ่ม MediaRouteButton ลงใน UI ของแอป การแตะ MediaRouteButton จะเปิดกล่องโต้ตอบที่แสดงรายการอุปกรณ์ที่พร้อมใช้งาน Cast ที่ใช้ได้ใน เครือข่าย เมื่อผู้ใช้เลือกอุปกรณ์ ระบบจะโอนการเล่นสื่อจาก อุปกรณ์เคลื่อนที่ไปยังอุปกรณ์รับที่เลือก ส่วนนี้จะแสดงวิธีเพิ่มปุ่มและรอรับเหตุการณ์เพื่ออัปเดต UI เมื่อการเล่นเปลี่ยนไปมาระหว่างอุปกรณ์ในพื้นที่และอุปกรณ์ระยะไกล

ตั้งค่า MediaRouteButton

คุณเพิ่ม MediaRouteButton ลงใน UI ของกิจกรรมได้ 4 วิธี ตัวเลือกที่ดีที่สุดจะขึ้นอยู่กับการออกแบบและข้อกำหนดของแอป

  • Compose UI: เพิ่ม Composable ของปุ่ม
  • UI ของยอดดู
    • เพิ่มปุ่มลงในเมนูแถบแอป
    • เพิ่มปุ่มภายใน PlayerView
    • เพิ่มปุ่มเป็น View มาตรฐาน
ภาพหน้าจอแสดงปุ่ม MediaRouteButton ใน UI
รูปที่ 2: (ก) MediaRouteButton ในแถบเมนู (ข) เป็น View (ค) ใน PlayerView และ (ง) กล่องโต้ตอบของอุปกรณ์ที่พร้อมใช้งาน Cast

เพิ่ม Composable MediaRouteButton ลงในเพลเยอร์

คุณเพิ่ม MediaRouteButton Composable ลงใน UI ของเพลเยอร์ได้ ดูข้อมูลเพิ่มเติมได้ที่คู่มือ Compose

Kotlin

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.media3.cast.MediaRouteButton

@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 ได้โดยตรงภายใน UI ของ PlayerView controls หลังจากตั้งค่า MediaController เป็นเพลเยอร์สำหรับ PlayerView แล้ว ให้ระบุ MediaRouteButtonViewProvider เพื่อแสดงปุ่มแคสต์ ในเพลเยอร์

Kotlin

override fun onStart() {
  super.onStart()

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

Java

@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>

Kotlin

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)
    ...
}

Java

@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);
    ...
}

เพิ่ม 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

Kotlin

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

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

Java

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

Activity Listener

สร้าง Player.Listener ใน Activity เพื่อฟังการเปลี่ยนแปลงตำแหน่งการเล่นสื่อ เมื่อplaybackTypeเปลี่ยนระหว่าง PLAYBACK_TYPE_LOCAL กับ PLAYBACK_TYPE_REMOTE คุณจะปรับ UI ได้ตามต้องการ หากต้องการป้องกันหน่วยความจำรั่วและจำกัดกิจกรรมของ Listener เฉพาะเมื่อแอปของคุณปรากฏ ให้ลงทะเบียน Listener ใน onStart และยกเลิกการลงทะเบียนใน onStop

Kotlin

import androidx.media3.common.DeviceInfo
import androidx.media3.common.Player

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)
}

Java

import androidx.media3.common.DeviceInfo;
import androidx.media3.common.Player;

private 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);
}

ดูข้อมูลเพิ่มเติมเกี่ยวกับการฟังและการตอบสนองต่อเหตุการณ์การเล่นได้ในคู่มือเหตุการณ์ของเพลเยอร์