به منظور استفاده از چارچوب MediaRouter در برنامه خود، باید یک نمونه از شی MediaRouter
دریافت کنید و یک شی MediaRouter.Callback
را برای گوش دادن به رویدادهای مسیریابی پیوست کنید. محتوای ارسال شده از طریق یک مسیر رسانه از طریق MediaRouteProvider
مرتبط با مسیر عبور می کند (به جز در چند مورد خاص، مانند دستگاه خروجی بلوتوث). شکل 1 نمای سطح بالایی از کلاس های مورد استفاده برای مسیریابی محتوا بین دستگاه ها را ارائه می دهد.
توجه: اگر میخواهید برنامه شما از دستگاههای Google Cast پشتیبانی کند، باید از Cast SDK استفاده کنید و برنامه خود را بهعنوان فرستنده Cast بسازید. به جای استفاده مستقیم از چارچوب MediaRouter، دستورالعملهای موجود در مستندات Cast را دنبال کنید.
دکمه مسیر رسانه
برنامه های اندروید باید از دکمه مسیر رسانه برای کنترل مسیریابی رسانه استفاده کنند. چارچوب MediaRouter یک رابط استاندارد برای دکمه فراهم میکند که به کاربران کمک میکند مسیریابی را زمانی که در دسترس است تشخیص دهند و از آن استفاده کنند. همانطور که در شکل 2 نشان داده شده است، دکمه مسیر رسانه معمولاً در سمت راست نوار عملکرد برنامه شما قرار می گیرد.
هنگامی که کاربر دکمه مسیر رسانه را فشار می دهد، مسیرهای رسانه موجود در لیستی مانند شکل 3 ظاهر می شوند.
برای ایجاد دکمه مسیر رسانه این مراحل را دنبال کنید:
- از AppCompatActivity استفاده کنید
- آیتم منو دکمه مسیر رسانه را تعریف کنید
- یک MediaRouteSelector ایجاد کنید
- دکمه مسیر رسانه را به نوار اقدام اضافه کنید
- روش های MediaRouter.Callback را در چرخه عمر فعالیت خود ایجاد و مدیریت کنید
این بخش چهار مرحله اول را شرح می دهد. بخش بعدی روش های Callback را توضیح می دهد.
از AppCompatActivity استفاده کنید
هنگامی که از چارچوب روتر رسانه در یک فعالیت استفاده می کنید، باید فعالیت را از AppCompatActivity
گسترش دهید و بسته androidx.appcompat.app
را وارد کنید. شما باید کتابخانه های پشتیبانی androidx.appcompat:appcompat و androidx.mediarouter:mediarouter را به پروژه توسعه برنامه خود اضافه کنید. برای اطلاعات بیشتر در مورد افزودن کتابخانه های پشتیبانی به پروژه خود، به شروع به کار با Android Jetpack مراجعه کنید.
احتیاط: حتماً از پیادهسازی androidx
چارچوب رسانه روتر استفاده کنید. از بسته قدیمیتر android.media
استفاده نکنید.
آیتم منو دکمه مسیر رسانه را تعریف کنید
یک فایل xml ایجاد کنید که یک آیتم منو برای دکمه مسیر رسانه تعریف کند. اکشن مورد باید کلاس MediaRouteActionProvider
باشد. در اینجا یک فایل نمونه است:
// myMediaRouteButtonMenuItem.xml <?xml version="1.0" encoding="utf-8"?> <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:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider" app:showAsAction="always" /> </menu>
یک MediaRouteSelector ایجاد کنید
مسیرهایی که در منوی دکمه مسیر رسانه ظاهر می شوند توسط MediaRouteSelector
تعیین می شوند. همانطور که در نمونه کد زیر نشان داده شده است، فعالیت خود را از AppCompatActivity
گسترش دهید و هنگامی که اکتیویتی با فراخوانی MediaRouteSelector.Builder
ایجاد شد، انتخابگر را بسازید. توجه داشته باشید که انتخابگر در یک متغیر کلاس ذخیره می شود و انواع مسیرهای مجاز با افزودن اشیاء MediaControlIntent
مشخص می شوند:
کاتلین
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mSelector: MediaRouteSelector? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create a route selector for the type of routes your app supports. mSelector = MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build() } }
جاوا
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouteSelector mSelector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create a route selector for the type of routes your app supports. mSelector = new MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build(); } }
برای اکثر برنامهها، تنها نوع مسیر مورد نیاز CATEGORY_REMOTE_PLAYBACK
است. این نوع مسیر با دستگاهی که برنامه شما را اجرا می کند به عنوان یک کنترل از راه دور برخورد می کند. دستگاه گیرنده متصل تمام بازیابی، رمزگشایی و پخش اطلاعات محتوا را کنترل می کند. برنامههایی که از Google Cast پشتیبانی میکنند، مانند Chromecast ، اینگونه کار میکنند.
تعدادی از تولیدکنندگان از یک گزینه مسیریابی ویژه به نام "خروجی ثانویه" پشتیبانی می کنند. با این مسیریابی، برنامه رسانه شما ویدیو یا موسیقی را مستقیماً روی صفحه و/یا بلندگوهای دستگاه گیرنده راه دور انتخابی بازیابی، رندر و پخش جریانی می کند. از خروجی ثانویه برای ارسال محتوا به سیستمهای موسیقی یا نمایشگرهای ویدیویی با قابلیت بیسیم استفاده کنید. برای فعال کردن کشف و انتخاب این دستگاهها، باید دستههای کنترل CATEGORY_LIVE_AUDIO
یا CATEGORY_LIVE_VIDEO
را به MediaRouteSelector اضافه کنید. همچنین باید گفتگوی Presentation
خود را ایجاد و مدیریت کنید.
دکمه مسیر رسانه را به نوار اقدام اضافه کنید
با تعریف منوی مسیر رسانه و MediaRouteSelector، اکنون می توانید دکمه مسیر رسانه را به یک فعالیت اضافه کنید. روش onCreateOptionsMenu()
را برای هر یک از فعالیت های خود نادیده بگیرید تا یک منوی گزینه اضافه کنید.
کاتلین
override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) // Inflate the menu and configure the media router action provider. menuInflater.inflate(R.menu.sample_media_router_menu, menu) // Attach the MediaRouteSelector to the menu item val mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item) val mediaRouteActionProvider = MenuItemCompat.getActionProvider(mediaRouteMenuItem) as MediaRouteActionProvider // Attach the MediaRouteSelector that you built in onCreate() selector?.also(mediaRouteActionProvider::setRouteSelector) // Return true to show the menu. return true }
جاوا
@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Inflate the menu and configure the media router action provider. getMenuInflater().inflate(R.menu.sample_media_router_menu, menu); // Attach the MediaRouteSelector to the menu item MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider)MenuItemCompat.getActionProvider( mediaRouteMenuItem); // Attach the MediaRouteSelector that you built in onCreate() mediaRouteActionProvider.setRouteSelector(selector); // Return true to show the menu. return true; }
برای اطلاعات بیشتر در مورد اجرای نوار اقدام در برنامه خود، به راهنمای توسعه دهنده Action Bar مراجعه کنید.
همچنین می توانید یک دکمه مسیر رسانه را به عنوان MediaRouteButton
در هر نما اضافه کنید. شما باید یک MediaRouteSelector را با استفاده از متد setRouteSelector()
به دکمه متصل کنید. برای دستورالعملهای مربوط به گنجاندن دکمه مسیر رسانه در برنامه خود، به چک لیست طراحی Google Cast مراجعه کنید.
تماس های MediaRouter
همه برنامههایی که روی یک دستگاه اجرا میشوند، یک نمونه MediaRouter
و مسیرهای آن را به اشتراک میگذارند (فیلتر شده در هر برنامه توسط MediaRouteSelector برنامه). هر فعالیت با استفاده از روش های MediaRouter.Callback
خود با MediaRouter ارتباط برقرار می کند. MediaRouter هر زمان که کاربر مسیری را انتخاب کند، تغییر دهد یا قطع کند، روشهای برگشت تماس را فراخوانی میکند.
روشهای مختلفی در callback وجود دارد که میتوانید برای دریافت اطلاعات در مورد رویدادهای مسیریابی، آنها را لغو کنید. حداقل، پیادهسازی کلاس MediaRouter.Callback
شما باید روی onRouteSelected()
و onRouteUnselected()
را لغو کند.
از آنجایی که MediaRouter یک منبع مشترک است، برنامه شما باید در پاسخ به تماسهای معمول چرخه حیات فعالیت، تماسهای MediaRouter خود را مدیریت کند:
- وقتی اکتیویتی ایجاد شد (
onCreate(Bundle)
) یک اشاره گر بهMediaRouter
بگیرید و برای تمام طول عمر برنامه روی آن نگه دارید. - وقتی اکتیویتی قابل مشاهده است (
onStart()
) فراخوان ها را به MediaRouter وصل کنید، و زمانی که مخفی شد (onStop()
) آنها را جدا کنید.
نمونه کد زیر نحوه ایجاد و ذخیره شئ برگشت تماس، نحوه به دست آوردن نمونه ای از MediaRouter
و نحوه مدیریت تماس های برگشتی را نشان می دهد. به استفاده از پرچم CALLBACK_FLAG_REQUEST_DISCOVERY
هنگام پیوست کردن تماسهای برگشتی در onStart()
توجه کنید. این به MediaRouteSelector شما اجازه میدهد تا فهرست مسیرهای موجود دکمه مسیر رسانه را بازخوانی کند.
کاتلین
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mediaRouter: MediaRouter? = null private var mSelector: MediaRouteSelector? = null // Variables to hold the currently selected route and its playback client private var mRoute: MediaRouter.RouteInfo? = null private var remotePlaybackClient: RemotePlaybackClient? = null // Define the Callback object and its methods, save the object in a class variable private val mediaRouterCallback = object : MediaRouter.Callback() { override fun onRouteSelected(router: MediaRouter, route: MediaRouter.RouteInfo) { Log.d(TAG, "onRouteSelected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Stop local playback (if necessary) // ... // Save the new route mRoute = route // Attach a new playback client remotePlaybackClient = RemotePlaybackClient(this@MediaRouterPlaybackActivity, mRoute) // Start remote playback (if necessary) // ... } } override fun onRouteUnselected( router: MediaRouter, route: MediaRouter.RouteInfo, reason: Int ) { Log.d(TAG, "onRouteUnselected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Changed route: tear down previous client mRoute?.also { remotePlaybackClient?.release() remotePlaybackClient = null } // Save the new route mRoute = route when (reason) { MediaRouter.UNSELECT_REASON_ROUTE_CHANGED -> { // Resume local playback (if necessary) // ... } } } } } // Retain a pointer to the MediaRouter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Get the media router service. mediaRouter = MediaRouter.getInstance(this) ... } // Use this callback to run your MediaRouteSelector to generate the // list of available media routes override fun onStart() { mSelector?.also { selector -> mediaRouter?.addCallback(selector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY) } super.onStart() } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. override fun onStop() { mediaRouter?.removeCallback(mediaRouterCallback) super.onStop() } ... }
جاوا
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouter mediaRouter; private MediaRouteSelector mSelector; // Variables to hold the currently selected route and its playback client private MediaRouter.RouteInfo mRoute; private RemotePlaybackClient remotePlaybackClient; // Define the Callback object and its methods, save the object in a class variable private final MediaRouter.Callback mediaRouterCallback = new MediaRouter.Callback() { @Override public void onRouteSelected(MediaRouter router, RouteInfo route) { Log.d(TAG, "onRouteSelected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Stop local playback (if necessary) // ... // Save the new route mRoute = route; // Attach a new playback client remotePlaybackClient = new RemotePlaybackClient(this, mRoute); // Start remote playback (if necessary) // ... } } @Override public void onRouteUnselected(MediaRouter router, RouteInfo route, int reason) { Log.d(TAG, "onRouteUnselected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Changed route: tear down previous client if (mRoute != null && remotePlaybackClient != null) { remotePlaybackClient.release(); remotePlaybackClient = null; } // Save the new route mRoute = route; if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) { // Resume local playback (if necessary) // ... } } } } // Retain a pointer to the MediaRouter @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get the media router service. mediaRouter = MediaRouter.getInstance(this); ... } // Use this callback to run your MediaRouteSelector to generate the list of available media routes @Override public void onStart() { mediaRouter.addCallback(mSelector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); super.onStart(); } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. @Override public void onStop() { mediaRouter.removeCallback(mediaRouterCallback); super.onStop(); } ... }
چارچوب مسیریاب رسانه همچنین یک کلاس MediaRouteDiscoveryFragment
را ارائه میکند که وظیفه افزودن و حذف پاسخ تماس برای یک فعالیت را بر عهده دارد.
توجه: اگر در حال نوشتن یک برنامه پخش موسیقی هستید و میخواهید برنامه در پسزمینه موسیقی پخش کند، باید یک Service
برای پخش بسازید و چارچوب روتر رسانه را از تماسهای چرخه حیات سرویس فراخوانی کنید.
کنترل یک مسیر پخش از راه دور
هنگامی که یک مسیر پخش از راه دور را انتخاب می کنید، برنامه شما به عنوان یک کنترل از راه دور عمل می کند. دستگاهی که در انتهای دیگر مسیر قرار دارد، تمام عملکردهای بازیابی، رمزگشایی و پخش اطلاعات محتوا را کنترل می کند. کنترلهای موجود در رابط کاربری برنامه شما با استفاده از یک شی RemotePlaybackClient
با دستگاه گیرنده ارتباط برقرار میکنند.
کلاس RemotePlaybackClient
روش های اضافی برای مدیریت پخش محتوا ارائه می دهد. در اینجا چند روش کلیدی پخش از کلاس RemotePlaybackClient
آورده شده است:
-
play()
- پخش یک فایل رسانه ای خاص، مشخص شده توسطUri
. -
pause()
- مکث آهنگ رسانه ای که در حال پخش است. -
resume()
- پس از دستور مکث به پخش آهنگ فعلی ادامه دهید. -
seek()
- به یک موقعیت خاص در مسیر فعلی حرکت کنید. -
release()
- اتصال برنامه خود به دستگاه پخش از راه دور را قطع کنید.
میتوانید از این روشها برای پیوست کردن کنشها به کنترلهای پخشی که در برنامه خود ارائه میدهید استفاده کنید. بسیاری از این روشها همچنین به شما امکان میدهند که یک شیء پاسخ به تماس را اضافه کنید تا بتوانید پیشرفت کار پخش یا درخواست کنترل را نظارت کنید.
کلاس RemotePlaybackClient
همچنین از صف بندی آیتم های رسانه ای متعدد برای پخش و مدیریت صف رسانه پشتیبانی می کند.
کد نمونه
نمونه های Android BasicMediaRouter و MediaRouter استفاده از MediaRouter API را بیشتر نشان می دهد.