«تعویضکننده خروجی» یکی از ویژگیهای Cast SDK است که از Android 13 به بعد، انتقال یکپارچه بین بازپخش محتوای محلی و ازراهدور را امکانپذیر میکند. هدف
کمک به برنامههای فرستنده برای کنترل آسان و سریع محل پخش محتوا است.
«تعویضکننده خروجی» از کتابخانه
MediaRouter برای
جابهجایی بازپخش محتوا بین بلندگوی تلفن، دستگاههای بلوتوث جفتشده،
و دستگاههای سازگار با Cast ازراهدور استفاده میکند. موارد استفاده را میتوان به سناریوهای زیر تقسیم کرد:
برنامه نمونه CastVideos-android را بارگیری و استفاده کنید تا با نحوه پیادهسازی «تعویضکننده خروجی» در برنامهتان آشنا شوید.
«تعویضکننده خروجی» باید فعال باشد تا از محلی به راه دور، راه دور به محلی، و راه دور به راه دور بااستفاده از مراحل پوششدادهشده در این راهنما پشتیبانی کند. برای پشتیبانی از انتقال بین بلندگوهای دستگاه محلی و دستگاههای بلوتوث مرتبطشده، به هیچ مرحله دیگری نیاز نیست.
واسط کاربر «تعویضکننده خروجی»
«تعویضکننده خروجی» دستگاههای محلی و ازراهدور دردسترس و همچنین وضعیت فعلی دستگاهها را نمایش میدهد، ازجمله اینکه آیا دستگاه انتخاب شده است، درحال اتصال است، و سطح صدای فعلی چقدر است. اگر علاوهبر دستگاه فعلی دستگاههای دیگری هم وجود داشته باشد، با کلیک کردن روی دستگاه دیگر میتوانید بازپخش رسانه را به دستگاه انتخابشده منتقل کنید.

مشکلات شناختهشده
- «جلسههای رسانه» ایجادشده برای بازپخش محلی هنگام جابهجایی به اعلان Cast SDK بسته و دوباره ایجاد خواهد شد.
نقطههای ورودی
اعلان رسانه
اگر برنامهای اعلان رسانهای با
MediaSession برای
بازپخش محلی (پخش محلی) پست کند، گوشه بالای اعلان رسانه
تراشه اعلانی را با نام دستگاهی (مثل بلندگوی تلفن) که
محتوا درحالحاضر در آن پخش میشود نشان میدهد. با تکضرب زدن روی تراشه اعلان،
رابط کاربری سیستم کادر گفتگوی «تعویضگر خروجی» باز میشود.

تنظیمات میزان صدا
رابط کاربری سیستم کادر گفتگوی «تعویضکننده خروجی» را میتوان با کلیک کردن روی دکمههای فیزیکی صدا در دستگاه، تکضرب زدن روی نماد تنظیمات در پایین، و تکضرب زدن روی نوشتار «پخش <نام برنامه> در <دستگاه پخش محتوا>» نیز فعال کرد.

خلاصه مراحل
- مطمئن شوید پیشنیازها برآورده شده باشد
- فعال کردن «تعویضکننده خروجی» در AndroidManifest.xml
- بهروزرسانی SessionManagerListener برای ارسال محتوا در پسزمینه
- افزودن پشتیبانی برای «از راه دور به از راه دور»
- تنظیم پرچم setRemoteToLocalEnabled
- ادامه بازپخش بهصورت محلی
پیشنیازها
- برنامه Android موجودتان را به AndroidX منتقل کنید.
build.gradleبرنامهتان را بهروز کنید تا از حداقل نسخه لازم «کیت توسعه نرمافزار فرستنده Android» برای «تعویضکننده خروجی» استفاده کند:dependencies { ... implementation 'com.google.android.gms:play-services-cast-framework:21.2.0' ... }
- برنامه از اعلانهای رسانه پشتیبانی میکند.
- دستگاه دارای Android 13.
راهاندازی اعلانهای رسانه
برای استفاده از «تعویضکننده خروجی»،
برنامههای صوتی و
ویدیویی
باید اعلان رسانهای ایجاد کنند تا وضعیت بازپخش و
کنترلهای رسانه را برای بازپخش محلی نمایش دهند. برای این کار باید
MediaSession ایجاد کنید،
MediaStyle را
با کد MediaSession تنظیم کنید، و کنترلهای رسانه را در
اعلان تنظیم کنید.
اگر درحالحاضر از MediaStyle و MediaSession استفاده نمیکنید، قطعه کد زیر نحوه راهاندازی آنها را نشان میدهد و راهنماهایی برای راهاندازی فراخوانیهای برگشتی جلسه رسانه برای برنامههای صوتی و ویدیویی دردسترس است:
// Create a media session. NotificationCompat.MediaStyle // PlayerService is your own Service or Activity responsible for media playback. val mediaSession = MediaSessionCompat(this, "PlayerService") // Create a MediaStyle object and supply your media session token to it. val mediaStyle = Notification.MediaStyle().setMediaSession(mediaSession.sessionToken) // Create a Notification which is styled by your MediaStyle object. // This connects your media session to the media controls. // Don't forget to include a small icon. val notification = Notification.Builder(this@PlayerService, CHANNEL_ID) .setStyle(mediaStyle) .setSmallIcon(R.drawable.ic_app_logo) .build() // Specify any actions which your users can perform, such as pausing and skipping to the next track. val pauseAction: Notification.Action = Notification.Action.Builder( pauseIcon, "Pause", pauseIntent ).build() notification.addAction(pauseAction)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { // Create a media session. NotificationCompat.MediaStyle // PlayerService is your own Service or Activity responsible for media playback. MediaSession mediaSession = new MediaSession(this, "PlayerService"); // Create a MediaStyle object and supply your media session token to it. Notification.MediaStyle mediaStyle = new Notification.MediaStyle().setMediaSession(mediaSession.getSessionToken()); // Specify any actions which your users can perform, such as pausing and skipping to the next track. Notification.Action pauseAction = Notification.Action.Builder(pauseIcon, "Pause", pauseIntent).build(); // Create a Notification which is styled by your MediaStyle object. // This connects your media session to the media controls. // Don't forget to include a small icon. String CHANNEL_ID = "CHANNEL_ID"; Notification notification = new Notification.Builder(this, CHANNEL_ID) .setStyle(mediaStyle) .setSmallIcon(R.drawable.ic_app_logo) .addAction(pauseAction) .build(); }

علاوهبراین، برای پر کردن اعلان با اطلاعات رسانه شما،
باید
فراداده و وضعیت بازپخش رسانه خود را
به MediaSession اضافه کنید.
برای افزودن فراداده به MediaSession، از
setMetaData()
استفاده کنید و همه ثابتهای
MediaMetadata مربوطه را برای
رسانهتان در
MediaMetadataCompat.Builder() ارائه دهید.
mediaSession.setMetadata(MediaMetadataCompat.Builder() // Title .putString(MediaMetadata.METADATA_KEY_TITLE, currentTrack.title) // Artist // Could also be the channel name or TV series. .putString(MediaMetadata.METADATA_KEY_ARTIST, currentTrack.artist) // Album art // Could also be a screenshot or hero image for video content // The URI scheme needs to be "content", "file", or "android.resource". .putString( MediaMetadata.METADATA_KEY_ALBUM_ART_URI, currentTrack.albumArtUri) ) // Duration // If duration isn't set, such as for live broadcasts, then the progress // indicator won't be shown on the seekbar. .putLong(MediaMetadata.METADATA_KEY_DURATION, currentTrack.duration) .build() )
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { mediaSession.setMetadata( new MediaMetadataCompat.Builder() // Title .putString(MediaMetadata.METADATA_KEY_TITLE, currentTrack.title) // Artist // Could also be the channel name or TV series. .putString(MediaMetadata.METADATA_KEY_ARTIST, currentTrack.artist) // Album art // Could also be a screenshot or hero image for video content // The URI scheme needs to be "content", "file", or "android.resource". .putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, currentTrack.albumArtUri) // Duration // If duration isn't set, such as for live broadcasts, then the progress // indicator won't be shown on the seekbar. .putLong(MediaMetadata.METADATA_KEY_DURATION, currentTrack.duration) .build() ); }

برای افزودن وضعیت بازپخش به MediaSession، از
setPlaybackState()
استفاده کنید و همه ثابتهای
PlaybackStateCompat
مربوطه را برای رسانهتان در
PlaybackStateCompat.Builder()
ارائه دهید.
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, // Playback position // Used to update the elapsed time and the progress bar. mediaPlayer.currentPosition.toLong(), // Playback speed // Determines the rate at which the elapsed time changes. playbackSpeed ) // isSeekable // Adding the SEEK_TO action indicates that seeking is supported // and makes the seekbar position marker draggable. If this is not // supplied seek will be disabled but progress will still be shown. .setActions(PlaybackStateCompat.ACTION_SEEK_TO) .build() )
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, // Playback position // Used to update the elapsed time and the progress bar. mediaPlayer.currentPosition.toLong(), // Playback speed // Determines the rate at which the elapsed time changes. playbackSpeed ) // isSeekable // Adding the SEEK_TO action indicates that seeking is supported // and makes the seekbar position marker draggable. If this is not // supplied seek will be disabled but progress will still be shown. .setActions(PlaybackStateCompat.ACTION_SEEK_TO) .build() ); }

رفتار اعلان برنامه ویدیویی
برنامههای ویدیویی یا برنامههای صوتی که از بازپخش محلی در پسزمینه پشتیبانی نمیکنند باید رفتار خاصی برای اعلانهای رسانه داشته باشند تا از بروز مشکل در ارسال فرمانهای رسانه در شرایطی که بازپخش پشتیبانی نمیشود جلوگیری شود:
- اعلان رسانه را وقتی رسانه بهطور محلی پخش میشود و برنامه در پیشزمینه است پست کنید.
- وقتی برنامه در پسزمینه است، بازپخش محلی را موقتاً متوقف کنید و اعلان را ببندید.
- وقتی برنامه به پیشزمینه برمیگردد، بازپخش محلی باید ازسر گرفته شود و اعلان باید دوباره پست شود.
فعال کردن «تعویضکننده خروجی» در AndroidManifest.xml
برای فعال کردن «تعویضکننده خروجی»،
MediaTransferReceiver
باید به AndroidManifest.xml برنامه اضافه شود. اگر اینطور نباشد، این ویژگی
فعال نخواهد شد و پرچم ویژگی «از راه دور به محلی» نیز نامعتبر خواهد بود.
<application>
...
<receiver
android:name="androidx.mediarouter.media.MediaTransferReceiver"
android:exported="true">
</receiver>
...
</application>
MediaTransferReceiver
گیرنده رویداد ثبتشدهای است که انتقال رسانه بین دستگاهها را با میانای کاربر سیستم ممکن میکند. برای اطلاعات بیشتر،
مرجع MediaTransferReceiver
را ببینید.
محلی به ازراهدور
وقتی کاربر پخش را از محلی به ازراهدور تغییر میدهد، Cast SDK جلسه Cast را بهطور خودکار شروع میکند. بااینحال، برنامهها باید جابهجایی از محلی به ازراهدور را مدیریت کنند، برای مثال، بازپخش محلی را متوقف کنند و رسانه را در دستگاه Cast بار کنند. برنامهها باید بااستفاده از فراخوانهای برگشتی
onSessionStarted()
و
onSessionEnded()
به Cast
SessionManagerListener
گوش دهند و هنگام دریافت فراخوانهای برگشتی Cast
SessionManager
کنش را مدیریت کنند. برنامهها باید مطمئن شوند که این فراخوانیهای برگشتی وقتی کادر گفتگوی «تعویضکننده خروجی» باز است و برنامه در پیشنما نیست همچنان فعال باشند.
بهروزرسانی SessionManagerListener برای پخش محتوا در پسزمینه
تجربه قدیمی Cast درحالحاضر از محلی به راه دور وقتی برنامه در پیشزمینه است پشتیبانی میکند. تجربه معمول Cast زمانی شروع میشود که کاربران روی نماد Cast در برنامه کلیک میکنند و دستگاهی را برای جاریسازی رسانه انتخاب میکنند. در این حالت، برنامه باید در
SessionManagerListener،
در onCreate() یا
onStart()
ثبت شود
و ثبت شنونده را در
onStop()
یا
onDestroy()
فعالیت برنامه لغو کند.
با تجربه جدید ارسال محتوا بااستفاده از «تعویضکننده خروجی»، برنامهها میتوانند
ارسال محتوا را وقتی در پسزمینه هستند شروع کنند. این ویژگی بهویژه برای برنامههای صوتی که هنگام پخش در پسزمینه اعلان پست میکنند مفید است. برنامهها میتوانند
شنوندگان SessionManager
را در onCreate() سرویس ثبت کنند و در onDestroy()
سرویس لغو ثبت کنند. برنامهها باید همیشه تماسهای برگشتی محلی به راه دور (مانند onSessionStarted) را وقتی برنامه در پسزمینه است دریافت کنند.
اگر برنامه از
MediaBrowserService استفاده میکند،
توصیه میشود SessionManagerListener را در آنجا
ثبت کنید.
class MyService : Service() { private var castContext: CastContext? = null protected fun onCreate() { castContext = CastContext.getSharedInstance(this) castContext .getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession::class.java) } protected fun onDestroy() { if (castContext != null) { castContext .getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession::class.java) } } }
public class MyService extends Service { private CastContext castContext; @Override protected void onCreate() { castContext = CastContext.getSharedInstance(this); castContext .getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession.class); } @Override protected void onDestroy() { if (castContext != null) { castContext .getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession.class); } } }
با این بهروزرسانی، وقتی برنامه در پسزمینه است، محلی به راه دور مانند ارسال محتوای معمولی عمل میکند و برای جابهجایی از دستگاههای بلوتوث به دستگاههای Cast به کار اضافی نیاز نیست.
ازراهدور به محلی
«تعویضکننده خروجی» امکان انتقال از بازپخش ازراهدور به بلندگوی تلفن یا دستگاه بلوتوث محلی را فراهم میکند. این ویژگی را میتوان با تنظیم کردن پرچم
setRemoteToLocalEnabled
روی true در CastOptions فعال کرد.
در مواردی که دستگاه فرستنده فعلی به جلسه موجود با چند فرستنده میپیوندد و برنامه باید بررسی کند که آیا رسانه فعلی مجاز به انتقال محلی است یا نه، برنامهها باید از فراخوان برگشتی onTransferred مربوط به SessionTransferCallback برای بررسی SessionState استفاده کنند.
پرچم setRemoteToLocalEnabled را تنظیم کنید
CastOptions.Builder
setRemoteToLocalEnabled را ارائه میدهد تا بلندگوی تلفن و دستگاههای بلوتوث محلی را بهعنوان هدفهای انتقال به
در کادر گفتگوی «تعویضگر خروجی» درصورت وجود جلسه فعال «پخش محتوا» نشان دهد یا پنهان کند.
class CastOptionsProvider : OptionsProvider { fun getCastOptions(context: Context?): CastOptions { ... return Builder() ... .setRemoteToLocalEnabled(true) .build() } }
public class CastOptionsProvider implements OptionsProvider { @Override public CastOptions getCastOptions(Context context) { ... return new CastOptions.Builder() ... .setRemoteToLocalEnabled(true) .build() } }
ادامه بازپخش بهصورت محلی
برنامههایی که از انتقال از راه دور به محلی پشتیبانی میکنند باید SessionTransferCallback را ثبت کنند تا هنگام وقوع رویداد مطلع شوند و بتوانند بررسی کنند که آیا انتقال رسانه مجاز است یا نه و بازپخش را بهصورت محلی ادامه دهند.
CastContext#addSessionTransferCallback(SessionTransferCallback)
به برنامه اجازه میدهد SessionTransferCallback خود را ثبت کند
و وقتی فرستنده به بازپخش محلی منتقل میشود،
به بازخوانهای onTransferred و onTransferFailed گوش دهد.
پساز اینکه برنامه SessionTransferCallback خود را لغو ثبتنام کرد،
برنامه دیگر SessionTransferCallback
دریافت نخواهد کرد.
SessionTransferCallback
افزونهای از فراخوانیهای برگشتی SessionManagerListener
موجود است و پساز فعال شدن onSessionEnded فعال میشود. ترتیب
فراخوانیهای برگشتی از راه دور به محلی عبارت است از:
onTransferringonSessionEndingonSessionEndedonTransferred
ازآنجاییکه «تعویضکننده خروجی» میتواند توسط تراشه اعلان رسانه وقتی برنامه در پسزمینه است و محتوا پخش میکند باز شود، برنامهها باید انتقال به محلی را بسته به اینکه از بازپخش پسزمینه پشتیبانی میکنند یا نه بهطور متفاوتی مدیریت کنند. درصورت
ناموفق بودن انتقال، onTransferFailed
هرزمان که خطا رخ دهد فعال میشود.
برنامههایی که از بازپخش پسزمینهای پشتیبانی میکنند
برای برنامههایی که از بازپخش در پسزمینه پشتیبانی میکنند (معمولاً برنامههای صوتی)،
توصیه میشود از Service (برای مثال MediaBrowserService) استفاده کنید. سرویسها
باید به onTransferred
فراخوان گوش دهند و بازپخش را بهصورت محلی هم وقتی برنامه در پیشزمینه است و هم وقتی در
پسزمینه است ازسر بگیرند.
class MyService : Service() { private var castContext: CastContext? = null private var sessionTransferCallback: SessionTransferCallback? = null protected fun onCreate() { castContext = CastContext.getSharedInstance(this) castContext.getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession::class.java) sessionTransferCallback = MySessionTransferCallback() castContext.addSessionTransferCallback(sessionTransferCallback) } protected fun onDestroy() { if (castContext != null) { castContext.getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession::class.java) if (sessionTransferCallback != null) { castContext.removeSessionTransferCallback(sessionTransferCallback) } } } class MySessionTransferCallback : SessionTransferCallback() { fun onTransferring(@SessionTransferCallback.TransferType transferType: Int) { // Perform necessary steps prior to onTransferred } fun onTransferred(@SessionTransferCallback.TransferType transferType: Int, sessionState: SessionState?) { if (transferType == SessionTransferCallback.TRANSFER_TYPE_FROM_REMOTE_TO_LOCAL) { // Remote stream is transferred to the local device. // Retrieve information from the SessionState to continue playback on the local player. } } fun onTransferFailed(@SessionTransferCallback.TransferType transferType: Int, @SessionTransferCallback.TransferFailedReason transferFailedReason: Int) { // Handle transfer failure. } } }
public class MyService extends Service { private CastContext castContext; private SessionTransferCallback sessionTransferCallback; @Override protected void onCreate() { castContext = CastContext.getSharedInstance(this); castContext.getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession.class); sessionTransferCallback = new MySessionTransferCallback(); castContext.addSessionTransferCallback(sessionTransferCallback); } @Override protected void onDestroy() { if (castContext != null) { castContext.getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession.class); if (sessionTransferCallback != null) { castContext.removeSessionTransferCallback(sessionTransferCallback); } } } public static class MySessionTransferCallback extends SessionTransferCallback { public MySessionTransferCallback() {} @Override public void onTransferring(@SessionTransferCallback.TransferType int transferType) { // Perform necessary steps prior to onTransferred } @Override public void onTransferred(@SessionTransferCallback.TransferType int transferType, SessionState sessionState) { if (transferType==SessionTransferCallback.TRANSFER_TYPE_FROM_REMOTE_TO_LOCAL) { // Remote stream is transferred to the local device. // Retrieve information from the SessionState to continue playback on the local player. } } @Override public void onTransferFailed(@SessionTransferCallback.TransferType int transferType, @SessionTransferCallback.TransferFailedReason int transferFailedReason) { // Handle transfer failure. } } }
برنامههایی که از بازپخش پسزمینهای پشتیبانی نمیکنند
برای برنامههایی که از بازپخش پسزمینه پشتیبانی نمیکنند (معمولاً برنامههای ویدیو)، توصیه میشود
به فراخوان onTransferred گوش دهید و اگر برنامه در پیشزمینه است، بازپخش را بهصورت محلی ازسر بگیرید.
اگر برنامه در پسزمینه باشد، باید بازپخش را موقتاً متوقف کند و اطلاعات لازم را از SessionState ذخیره کند (برای مثال، فراداده رسانه و موقعیت بازپخش). وقتی برنامه از پسزمینه به پیشزمینه میآید، بازپخش محلی باید با اطلاعات ذخیرهشده ادامه یابد.
class MyActivity : AppCompatActivity() { private var castContext: CastContext? = null private var sessionTransferCallback: SessionTransferCallback? = null protected fun onCreate() { castContext = CastContext.getSharedInstance(this) castContext.getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession::class.java) sessionTransferCallback = MySessionTransferCallback() castContext.addSessionTransferCallback(sessionTransferCallback) } protected fun onDestroy() { if (castContext != null) { castContext.getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession::class.java) if (sessionTransferCallback != null) { castContext.removeSessionTransferCallback(sessionTransferCallback) } } } class MySessionTransferCallback : SessionTransferCallback() { fun onTransferring(@SessionTransferCallback.TransferType transferType: Int) { // Perform necessary steps prior to onTransferred } fun onTransferred(@SessionTransferCallback.TransferType transferType: Int, sessionState: SessionState?) { if (transferType == SessionTransferCallback.TRANSFER_TYPE_FROM_REMOTE_TO_LOCAL) { // Remote stream is transferred to the local device. // Retrieve information from the SessionState to continue playback on the local player. } } fun onTransferFailed(@SessionTransferCallback.TransferType transferType: Int, @SessionTransferCallback.TransferFailedReason transferFailedReason: Int) { // Handle transfer failure. } } }
public class MyActivity extends AppCompatActivity { private CastContext castContext; private SessionTransferCallback sessionTransferCallback; @Override protected void onCreate() { castContext = CastContext.getSharedInstance(this); castContext .getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession.class); sessionTransferCallback = new MySessionTransferCallback(); castContext.addSessionTransferCallback(sessionTransferCallback); } @Override protected void onDestroy() { if (castContext != null) { castContext .getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession.class); if (sessionTransferCallback != null) { castContext.removeSessionTransferCallback(sessionTransferCallback); } } } public static class MySessionTransferCallback extends SessionTransferCallback { public MySessionTransferCallback() {} @Override public void onTransferring(@SessionTransferCallback.TransferType int transferType) { // Perform necessary steps prior to onTransferred } @Override public void onTransferred(@SessionTransferCallback.TransferType int transferType, SessionState sessionState) { if (transferType==SessionTransferCallback.TRANSFER_TYPE_FROM_REMOTE_TO_LOCAL) { // Remote stream is transferred to the local device. // Retrieve information from the SessionState to continue playback on the local player. } } @Override public void onTransferFailed(@SessionTransferCallback.TransferType int transferType, @SessionTransferCallback.TransferFailedReason int transferFailedReason) { // Handle transfer failure. } } }
ازراهدور به ازراهدور
«تعویضکننده خروجی» از قابلیت گسترش به چندین دستگاه بلندگوی سازگار با Cast برای برنامههای صوتی بااستفاده از «گسترش جاریسازی» پشتیبانی میکند.
برنامههای صوتی برنامههایی هستند که از Google Cast برای صدا در تنظیمات برنامه گیرنده در کنسول توسعهدهنده Google Cast SDK پشتیبانی میکنند.

«گسترش جاریسازی» با بلندگوها
برنامههای صوتی که از «تعویضکننده خروجی» استفاده میکنند میتوانند بااستفاده از «گسترش جاریسازی» درطول جلسه Cast، صدا را به چندین دستگاه بلندگوی سازگار با Cast گسترش دهند.
این ویژگی توسط پلاتفرم Cast پشتیبانی میشود و اگر برنامه از واسط کاربر پیشفرض استفاده میکند، به تغییرات بیشتری نیاز ندارد. اگر از میانای کاربر سفارشی استفاده میشود، برنامه باید میانای کاربر را بهروز کند تا نشان دهد برنامه درحال ارسال محتوا به گروه است.

برای دریافت نام گروه گسترشیافته جدید درطول گسترش جاریسازی،
Cast.Listener
را بااستفاده از
CastSession#addCastListener
ثبت کنید.
سپس درطول تماس برگشتی onDeviceNameChanged، با
CastSession#getCastDevice()
تماس بگیرید.
class MyActivity : Activity() { private var mCastSession: CastSession? = null private lateinit var mCastContext: CastContext private lateinit var mSessionManager: SessionManager private val mSessionManagerListener: SessionManagerListener<CastSession> = SessionManagerListenerImpl() private val mCastListener = CastListener() private inner class SessionManagerListenerImpl : SessionManagerListener<CastSession?> { override fun onSessionStarting(session: CastSession?) {} override fun onSessionStarted(session: CastSession?, sessionId: String) { addCastListener(session) } override fun onSessionStartFailed(session: CastSession?, error: Int) {} override fun onSessionSuspended(session: CastSession?, reason Int) { removeCastListener() } override fun onSessionResuming(session: CastSession?, sessionId: String) {} override fun onSessionResumed(session: CastSession?, wasSuspended: Boolean) { addCastListener(session) } override fun onSessionResumeFailed(session: CastSession?, error: Int) {} override fun onSessionEnding(session: CastSession?) {} override fun onSessionEnded(session: CastSession?, error: Int) { removeCastListener() } } private inner class CastListener : Cast.Listener() { override fun onDeviceNameChanged() { mCastSession?.let { val castDevice = it.castDevice val deviceName = castDevice.friendlyName // Update UIs with the new cast device name. } } } private fun addCastListener(castSession: CastSession) { mCastSession = castSession mCastSession?.addCastListener(mCastListener) } private fun removeCastListener() { mCastSession?.removeCastListener(mCastListener) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mCastContext = CastContext.getSharedInstance(this) mSessionManager = mCastContext.sessionManager mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession::class.java) } override fun onDestroy() { super.onDestroy() mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession::class.java) } }
public class MyActivity extends Activity { private CastContext mCastContext; private CastSession mCastSession; private SessionManager mSessionManager; private SessionManagerListener<CastSession> mSessionManagerListener = new SessionManagerListenerImpl(); private Cast.Listener mCastListener = new CastListener(); private class SessionManagerListenerImpl implements SessionManagerListener<CastSession> { @Override public void onSessionStarting(CastSession session) {} @Override public void onSessionStarted(CastSession session, String sessionId) { addCastListener(session); } @Override public void onSessionStartFailed(CastSession session, int error) {} @Override public void onSessionSuspended(CastSession session, int reason) { removeCastListener(); } @Override public void onSessionResuming(CastSession session, String sessionId) {} @Override public void onSessionResumed(CastSession session, boolean wasSuspended) { addCastListener(session); } @Override public void onSessionResumeFailed(CastSession session, int error) {} @Override public void onSessionEnding(CastSession session) {} @Override public void onSessionEnded(CastSession session, int error) { removeCastListener(); } } private class CastListener extends Cast.Listener { @Override public void onDeviceNameChanged() { if (mCastSession == null) { return; } CastDevice castDevice = mCastSession.getCastDevice(); String deviceName = castDevice.getFriendlyName(); // Update UIs with the new cast device name. } } private void addCastListener(CastSession castSession) { mCastSession = castSession; mCastSession.addCastListener(mCastListener); } private void removeCastListener() { if (mCastSession != null) { mCastSession.removeCastListener(mCastListener); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCastContext = CastContext.getSharedInstance(this); mSessionManager = mCastContext.getSessionManager(); mSessionManager.addSessionManagerListener(mSessionManagerListener, CastSession.class); } @Override protected void onDestroy() { super.onDestroy(); mSessionManager.removeSessionManagerListener(mSessionManagerListener, CastSession.class); } }
درحال آزمایش از راه دور به از راه دور
برای آزمایش کردن این ویژگی:
- محتوایتان را بااستفاده از پخش محتوای معمولی یا با محلی به راه دور به دستگاه سازگار با Cast ارسال کنید.
- «تعویضگر خروجی» را بااستفاده از یکی از نقاط ورودی باز کنید.
- روی دستگاه دیگری که با Cast سازگار است تکضرب بزنید، برنامههای صوتی محتوا را به دستگاه دیگر گسترش میدهند و گروهی پویا ایجاد میکنند.
- دوباره روی دستگاه سازگار با Cast تکضرب بزنید تا از گروه پویا برداشته شود.