CastPlayer הוא הטמעה של נגן Jetpack Media3 שתומך גם בהפעלה מקומית וגם בהעברה למכשיר מרוחק שתומך ב-Cast. CastPlayer
מפשט את הוספת פונקציונליות ההעברה לאפליקציה ומספק תכונות עשירות למעבר חלק בין הפעלה מקומית להפעלה מרחוק. במדריך הזה מוסבר איך לשלב את CastPlayer באפליקציית המדיה שלכם.
כדי לשלב את Cast עם פלטפורמות אחרות, אפשר לעיין ב-Cast SDK.
מכשיר שתומך ב-Cast
כדי לבדוק את CastPlayer, צריך מכשיר שתומך ב-Cast. האפשרויות כוללות Android TV, Chromecast, רמקולים חכמים ומסכים חכמים. מוודאים שהמכשיר מוגדר ומחובר לאותה רשת Wi-Fi שאליה מחובר המכשיר הנייד שמשמש לפיתוח.
הוספת יחסי תלות ב-build
כדי להתחיל להשתמש ב-CastPlayer, מוסיפים את יחסי התלות של AndroidX Media3 ו-CastPlayer לקובץ build.gradle של מודול האפליקציה.
Kotlin
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, האפליקציה צריכה להיות מסוגלת לנהל את ההפעלה גם כשהמשתמש לא מבצע אינטראקציה עם Activity מהאפליקציה, למשל דרך ההתראה על המדיה במערכת. לכן, צריך ליצור את המכונות של ExoPlayer (להפעלה מקומית) ו-CastPlayer (להפעלה מרחוק) בשירות, כמו MediaSessionService או MediaLibraryService.
קודם יוצרים את המכונה של ExoPlayer, ואז כשיוצרים את המכונה של CastPlayer, מגדירים את ExoPlayer כמכונה של הנגן המקומי. אחר כך תוכלו להעביר את הפעלת המדיה בין הנייד למכשיר שתומך ב-Cast דרך ההתראה על המדיה או ההתראה במסך הנעילה. Media3 משתמש בתכונה Output Switcher כדי לטפל בהעברות של הנגן כשנתיב הפלט משתנה ממקומי למרוחק או ממרוחק למקומי.
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(); }
הוספת רכיבים בממשק המשתמש
מוסיפים MediaRouteButton לממשק המשתמש של האפליקציה. לחיצה על MediaRouteButton פותחת תיבת דו-שיח עם רשימה של מכשירים ברשת שתומכים ב-Cast. כשהמשתמש בוחר מכשיר, הפעלת המדיה מועברת מהנייד למכשיר המקלט שנבחר. בקטע הזה מוסבר איך להוסיף את הכפתור ולהאזין לאירועים כדי לעדכן את ממשק המשתמש כשההפעלה עוברת בין מכשירים מקומיים למכשירים שמחוברים לרשת אחרת.
הגדרת MediaRouteButton
יש ארבע דרכים להוסיף את MediaRouteButton לממשק המשתמש של הפעילות. האפשרות הטובה ביותר תלויה בעיצוב ובדרישות של האפליקציה.
- ממשק משתמש של Compose: מוסיפים כפתור קומפוזבילי.
- ממשק המשתמש של התצוגות:
- מוסיפים את הכפתור לתפריט של סרגל האפליקציה.
- מוסיפים את הכפתור בתוך
PlayerView. - מוסיפים את הכפתור כ-
Viewרגיל.
הוספת Composable MediaRouteButton לנגן
אתם יכולים להוסיף את ה-Composable MediaRouteButton לממשק המשתמש של הנגן. מידע נוסף זמין במדריך בנושא Compose.
@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 כדי להציג את הכפתור להפעלת Cast בנגן.
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, ) // ... return true }
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); // ... return true; }
מוסיפים את MediaRouteButton כתצוגה
אתם יכולים להגדיר MediaRouteButton בקובץ 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) { super.onCreate(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, אתם יכולים לשנות את ממשק המשתמש לפי הצורך. כדי למנוע דליפות זיכרון ולהגביל את פעילות המאזין רק כשהאפליקציה גלויה, צריך לרשום את המאזין ב-onStart ולבטל את הרישום שלו ב-onStop:
Kotlin
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
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); }
במדריך בנושא אירועי נגן מוסבר איך להאזין לאירועי הפעלה ולהגיב להם.