CastPlayer هو تنفيذ مشغّل Jetpack Media3 يتيح التشغيل على الجهاز وإرسال المحتوى إلى جهاز خارجي متوافق مع تكنولوجيا Google Cast. CastPlayer
تسهّل إضافة وظيفة البث إلى تطبيقك وتوفّر ميزات غنية تتيح التبديل بسلاسة بين التشغيل المحلي والتشغيل عن بُعد. يوضّح لك هذا الدليل كيفية دمج CastPlayer في تطبيق الوسائط.
لدمج Cast مع منصات أخرى، يُرجى الاطّلاع على حزمة تطوير البرامج (SDK) الخاصة بـ Cast.
إضافة CastPlayer كعنصر تابع
لبدء استخدام CastPlayer، أضِف الاعتماديات المطلوبة في AndroidX Media3 وCastPlayer إلى ملف build.gradle الخاص بوحدة تطبيقك.
Kotlin
implementation("androidx.media3:media3-exoplayer:1.9.0-alpha01") implementation("androidx.media3:media3-ui:1.9.0-alpha01") implementation("androidx.media3:media3-session:1.9.0-alpha01") implementation("androidx.media3:media3-cast:1.9.0-alpha01")
Groovy
implementation "androidx.media3:media3-exoplayer:1.9.0-alpha01" implementation "androidx.media3:media3-ui:1.9.0-alpha01" implementation "androidx.media3:media3-session:1.9.0-alpha01" implementation "androidx.media3:media3-cast:1.9.0-alpha01"
راجِع ملاحظات إصدار Jetpack Media للعثور على أحدث إصدار أولي حتى تتمكّن من دمج CastPlayer في تطبيقك، علمًا بأنّه يجب أن تكون جميع الوحدات النمطية من الإصدار نفسه.
لمزيد من المعلومات حول وحدات المكتبة المتاحة، راجِع صفحة Google Maven AndroidX Media3.
إعداد CastPlayer
لضبط CastPlayer، عدِّل ملف AndroidManifest.xml باستخدام موفّر خيارات.
موفّر الخيارات
يتطلّب CastPlayer موفّر خيارات لضبط سلوكه. لإعداد بسيط، يمكنك استخدام موفّر الخيارات التلقائي من خلال إضافته إلى ملف 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 إلى ملف البيان إلى تمكين واجهة مستخدم النظام من إعادة توجيه الوسائط بدون فتح نشاط التطبيق. على سبيل المثال، يمكن للمستخدم تغيير الجهاز الذي يتم تشغيل وسائط تطبيقك عليه من خلال إشعار الوسائط.
<application>
<receiver android:name="androidx.mediarouter.media.MediaTransferReceiver" />
</application>
إنشاء CastPlayer
عند تشغيل المحتوى عن بُعد باستخدام Cast، يجب أن يتمكّن تطبيقك من إدارة التشغيل حتى عندما لا يتفاعل المستخدم مع نشاط من تطبيقك، مثلاً من خلال إشعار الوسائط في النظام. لهذا السبب، يجب إنشاء مثيلات ExoPlayer (للتشغيل المحلي) وCastPlayer (للتشغيل عن بُعد) في خدمة، مثل MediaSessionService أو MediaLibraryService. أولاً، أنشئ مثيل ExoPlayer، ثم عند إنشاء مثيل CastPlayer، اضبط ExoPlayer كمثيل مشغّل محلي. سيصبح بإمكان Media3 بعد ذلك التعامل مع عمليات نقل المشغّل عند تغيير مسار الإخراج من جهاز محلي إلى جهاز بعيد أو من جهاز بعيد إلى جهاز محلي.
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 إلى واجهة مستخدم تطبيقك للسماح للمستخدمين باختيار جهاز Cast.
يوضّح لك هذا القسم كيفية إضافة الزر ومعالجة الأحداث لتعديل واجهة المستخدم عند التبديل بين تشغيل المحتوى على الجهاز المحلي والجهاز البعيد.
ضبط MediaRouteButton
هناك أربع طرق محتملة لإضافة MediaRouteButton إلى واجهة المستخدم الخاصة بنشاطك ليتفاعل معها المستخدمون. سيعتمد الاختيار على المظهر الذي تريده لواجهة المستخدم الخاصة بنشاط اللاعبين وطريقة عملها.
إضافة زر مسار وسائط قابل للإنشاء إلى "المشغّل"
يمكنك إضافة العنصر القابل للإنشاء MediaRouteButton إلى واجهة مستخدم المشغّل. لمزيد من المعلومات، يُرجى الاطّلاع على دليل إنشاء.
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) { ... }
إضافة زر مسار الوسائط إلى PlayerView
يمكنك إضافة MediaRouteButton مباشرةً ضمن عناصر تحكّم واجهة المستخدم في PlayerView. بعد ضبط 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()); }
إضافة زر مسار الوسائط إلى قائمة شريط التطبيق
تُعدّ هذه الطريقة زر مسار الوسائط في قائمة شريط التطبيق. يجب إجراء تعديلات على كل من ملف البيان و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 في ملف activity layout.xml.
لإكمال عملية إعداد MediaRouteButton، استخدِم MediaRouteButtonFactory Media3 Cast في رمز 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); }
أداة معالجة النشاط
أنشئ Player.Listener في Activity للاستماع إلى التغييرات في الموقع الجغرافي لتشغيل الوسائط. عندما يتغيّر playbackType بين PLAYBACK_TYPE_LOCAL
وPLAYBACK_TYPE_REMOTE، يمكنك تعديل واجهة المستخدم حسب الحاجة. لمنع تسرُّب الذاكرة وحصر نشاط أداة معالجة الأحداث في الحالات التي يكون فيها تطبيقك مرئيًا فقط، سجِّل أداة معالجة الأحداث في 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); }
لمزيد من المعلومات حول الاستماع إلى أحداث التشغيل والاستجابة لها، يُرجى الاطّلاع على دليل أحداث المشغّل.