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


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

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

خلاصه مراحل
- اطمینان از رعایت پیشنیازها
- فعال کردن Output Switcher در AndroidManifest.xml
- بهروزرسانی SessionManagerListener برای ارسال در پسزمینه
- اضافه شدن پشتیبانی از ارتباط از راه دور به راه دور
- پرچم setRemoteToLocalEnabled را تنظیم کنید.
- پخش را به صورت محلی ادامه دهید
پیشنیازها
- برنامه اندروید موجود خود را به AndroidX منتقل کنید.
-
build.gradleبرنامه خود را بهروزرسانی کنید تا از حداقل نسخه مورد نیاز Android Sender SDK برای Output Switcher استفاده کند:dependencies { ... implementation 'com.google.android.gms:play-services-cast-framework:21.2.0' ... }
- برنامه از اعلانهای رسانهای پشتیبانی میکند.
- دستگاهی که اندروید ۱۳ را اجرا میکند.
اعلانهای رسانهای را تنظیم کنید
برای استفاده از Output Switcher، برنامههای صوتی و تصویری باید یک اعلان رسانهای ایجاد کنند تا وضعیت پخش و کنترلهای مربوط به رسانههای خود را برای پخش محلی نمایش دهند. این کار مستلزم ایجاد یک 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() ); }

رفتار اعلان برنامه ویدیویی
برنامههای ویدیویی یا برنامههای صوتی که از پخش محلی در پسزمینه پشتیبانی نمیکنند، باید رفتار خاصی برای اعلانهای رسانهای داشته باشند تا از بروز مشکلات مربوط به ارسال دستورات رسانهای در موقعیتهایی که پخش پشتیبانی نمیشود، جلوگیری شود:
- اعلان رسانه را هنگام پخش رسانه به صورت محلی ارسال کنید و برنامه در پیشزمینه باشد.
- وقتی برنامه در پسزمینه است، پخش محلی را متوقف کنید و اعلان را رد کنید.
- وقتی برنامه به پیشزمینه برمیگردد، پخش محلی باید از سر گرفته شود و اعلان باید دوباره ارسال شود.
فعال کردن Output Switcher در AndroidManifest.xml
برای فعال کردن Output Switcher، باید MediaTransferReceiver به AndroidManifest.xml برنامه اضافه شود. اگر اضافه نشود، این ویژگی فعال نخواهد شد و پرچم ویژگی remote-to-local نیز نامعتبر خواهد بود.
<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 اقدامات لازم را انجام دهند. برنامهها باید اطمینان حاصل کنند که این فراخوانیها هنگام باز شدن کادر محاورهای Output Switcher و عدم نمایش برنامه در پیشزمینه، همچنان فعال هستند.
بهروزرسانی SessionManagerListener برای ارسال در پسزمینه
تجربه قدیمی Cast از قبل از انتقال محلی به راه دور، زمانی که برنامه در پیشزمینه است، پشتیبانی میکند. یک تجربه Cast معمولی زمانی شروع میشود که کاربران روی آیکون Cast در برنامه کلیک میکنند و دستگاهی را برای پخش رسانه انتخاب میکنند. در این حالت، برنامه باید در onCreate() یا onStart() در SessionManagerListener ثبت شود و در onStop() یا onDestroy() از activity برنامه، شنونده را لغو ثبت کند.
با تجربه جدید ارسال با استفاده از Output Switcher، برنامهها میتوانند وقتی در پسزمینه هستند، شروع به ارسال کنند. این امر به ویژه برای برنامههای صوتی که هنگام پخش در پسزمینه اعلان ارسال میکنند، مفید است. برنامهها میتوانند شنوندههای 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); } } }
با این بهروزرسانی، وقتی برنامه در پسزمینه است، انتقال از محلی به راه دور مانند انتقال معمولی عمل میکند و برای تغییر از دستگاههای بلوتوث به دستگاههای انتقال نیازی به کار اضافی نیست.
از راه دور به محلی
سوئیچر خروجی امکان انتقال از پخش از راه دور به بلندگوی تلفن یا دستگاه بلوتوث محلی را فراهم میکند. این قابلیت را میتوان با تنظیم پرچم setRemoteToLocalEnabled روی true در CastOptions فعال کرد.
برای مواردی که دستگاه فرستنده فعلی به یک جلسه موجود با چندین فرستنده میپیوندد و برنامه باید بررسی کند که آیا رسانه فعلی اجازه انتقال محلی را دارد یا خیر، برنامهها باید از فراخوانی onTransferred از SessionTransferCallback برای بررسی SessionState استفاده کنند.
پرچم setRemoteToLocalEnabled را تنظیم کنید.
CastOptions.Builder یک setRemoteToLocalEnabled ارائه میدهد تا بلندگوی تلفن و دستگاههای بلوتوث محلی را به عنوان اهداف انتقال به (transfer-to) در پنجرهی Output Switcher، زمانی که یک جلسهی فعال Cast وجود دارد، نمایش یا پنهان کند.
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 فعال میشود. ترتیب فراخوانیهای remote به local به شرح زیر است:
-
onTransferring -
onSessionEnding -
onSessionEnded -
onTransferred
از آنجایی که سوئیچر خروجی میتواند توسط تراشه اعلان رسانهای زمانی که برنامه در پسزمینه است و در حال ارسال است، باز شود، برنامهها باید بسته به اینکه آیا از پخش پسزمینه پشتیبانی میکنند یا خیر، انتقال به محلی را به طور متفاوتی مدیریت کنند. در صورت انتقال ناموفق، 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 برای برنامههای صوتی با استفاده از Stream Expansion پشتیبانی میکند.
برنامههای صوتی، برنامههایی هستند که از Google Cast برای صدا در تنظیمات برنامه گیرنده در کنسول توسعهدهندگان Google Cast SDK پشتیبانی میکنند.

گسترش جریان با بلندگوها
برنامههای صوتی که از Output Switcher استفاده میکنند، این قابلیت را دارند که در طول یک جلسه Cast، با استفاده از Stream Expansion، صدا را به چندین دستگاه بلندگوی دارای قابلیت Cast گسترش دهند.
این ویژگی توسط پلتفرم Cast پشتیبانی میشود و در صورت استفاده از رابط کاربری پیشفرض برنامه، نیازی به تغییر بیشتر ندارد. در صورت استفاده از رابط کاربری سفارشی، برنامه باید رابط کاربری را بهروزرسانی کند تا نشان دهد که برنامه در حال ارسال به یک گروه است.


برای دریافت نام گروه بسطیافته جدید در طول بسط جریان، با استفاده از CastSession#addCastListener یک Cast.Listener ثبت کنید. سپس در طول فراخوانی 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); } }
آزمایش از راه دور به راه دور
برای آزمایش ویژگی:
- محتوای خود را با استفاده از پخش معمولی یا با استفاده از مبدل محلی به راه دور، به دستگاهی که از پخش پشتیبانی میکند، پخش کنید.
- با استفاده از یکی از نقاط ورودی، Output Switcher را باز کنید.
- روی دستگاه دیگری که از Cast پشتیبانی میکند ضربه بزنید، برنامههای صوتی محتوا را به دستگاه اضافی گسترش میدهند و یک گروه پویا ایجاد میکنند.
- دوباره روی دستگاهی که Cast روی آن فعال است ضربه بزنید، از گروه پویا حذف خواهد شد.