Çıkış Değiştirici, Android 13'ten itibaren içeriğin yerel ve uzak oynatımı arasında sorunsuz geçiş yapmanızı sağlayan Cast SDK'sının bir özelliğidir. Amaç, gönderen uygulamaların içeriğin nerede oynatıldığını kolay ve hızlı bir şekilde kontrol etmesine yardımcı olmaktır.
Çıkış değiştirici, içerik oynatmayı telefon hoparlörü, eşlenen Bluetooth cihazlar ve uzak Cast uyumlu cihazlar arasında geçiş yapmak için MediaRouter
kitaplığını kullanır. Kullanım alanları aşağıdaki senaryolara ayrılabilir:
Çıkış Değiştirici'yi uygulamanıza nasıl uygulayacağınızla ilgili referans için CastVideos-android örnek uygulamasını indirip kullanın.
Bu kılavuzda açıklanan adımları uygulayarak çıkış değiştirici, yerelden uzaktan, uzaktan yerele ve uzaktan uzaktan bağlantıları desteklemek için etkinleştirilmelidir. Yerel cihaz hoparlörleri ile eşlenen Bluetooth cihazlar arasında aktarımı desteklemek için ek adımlar gerekmez.
Çıkış Değiştirici kullanıcı arayüzü
Çıkış Değiştirici, kullanılabilir yerel ve uzak cihazların yanı sıra cihazın seçili olup olmadığı, bağlanıp bağlanmadığı ve mevcut ses seviyesi gibi mevcut cihaz durumlarını gösterir. Mevcut cihaza ek olarak başka cihazlar varsa diğer cihazı tıklayarak medya oynatmayı seçili cihaza aktarabilirsiniz.
Bilinen sorunlar
- Yerel oynatma için oluşturulan medya oturumları, Cast SDK bildirimine geçiş yapıldığında kapatılır ve yeniden oluşturulur.
Giriş noktaları
Medya bildirimi
Bir uygulama, yerel oynatma (yerel olarak oynatma) için MediaSession
içeren bir medya bildirimi yayınlarsa medya bildiriminin sağ üst köşesinde, içeriğin şu anda oynatıldığı cihazın adını (ör. telefon hoparlörü) içeren bir bildirim çipi gösterilir. Bildirim çipine dokunduğunuzda Çıkış Değiştirici iletişim kutusu sistem kullanıcı arayüzü açılır.
Ses düzeyi ayarları
Çıkış Değiştirici iletişim kutusu sistem kullanıcı arayüzü, cihazdaki fiziksel ses düğmelerini tıklayarak, alt kısımdaki ayarlar simgesine ve "<Uygulama Adı>yı <Yayınlama Cihazı>nda oynat" metnine dokunarak da tetiklenebilir.
Adımların özeti
- Ön koşulların karşılandığından emin olma
- AndroidManifest.xml dosyasında Çıkış Değiştirici'yi etkinleştirme
- Arka planda yayınlama için SessionManagerListener'ı güncelleme
- Uzaktan-uzaktan bağlantı desteği ekleme
- setRemoteToLocalEnabled işaretini ayarlama
- Oynatma işlemine yerel olarak devam etme
Ön koşullar
- Mevcut Android uygulamanızı AndroidX'e taşıyın.
- Çıkış Değiştirici için Android Gönderen SDK'sının minimum gerekli sürümünü kullanacak şekilde uygulamanızın
build.gradle
dosyasını güncelleyin:dependencies { ... implementation 'com.google.android.gms:play-services-cast-framework:21.2.0' ... }
- Uygulama, medya bildirimlerini desteklemelidir.
- Android 13 yüklü cihaz.
Medya Bildirimleri'ni ayarlama
Çıkış Değiştirici'yi kullanmak için ses ve video uygulamalarının, yerel oynatma için medyalarının oynatma durumunu ve kontrollerini gösteren bir medya bildirimi oluşturması gerekir. Bunun için bir MediaSession
oluşturmanız, MediaSession
jetonuyla MediaStyle
ayarlarını yapmanız ve bildirimdeki medya denetimlerini ayarlamanız gerekir.
Şu anda MediaStyle
ve MediaSession
kullanmıyorsanız bunların nasıl ayarlanacağını aşağıdaki snippet'te görebilirsiniz. Ses ve video uygulamaları için medya oturumu geri çağırma işlevlerini ayarlamayla ilgili kılavuzlar da mevcuttur:
// 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(); }
Ayrıca, bildirimi medyanızla ilgili bilgilerle doldurmak için MediaSession
alanına medyanızın meta verilerini ve oynatma durumunu eklemeniz gerekir.
MediaSession
öğesine meta veri eklemek için setMetaData()
kullanın ve medyanızla ilgili tüm ilgili MediaMetadata
sabitlerini MediaMetadataCompat.Builder()
içinde sağlayın.
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() ); }
Oynatma durumunu MediaSession
öğesine eklemek için setPlaybackState()
öğesini kullanın ve medyanızla ilgili tüm ilgili PlaybackStateCompat
sabitlerini PlaybackStateCompat.Builder()
içinde sağlayın.
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() ); }
Video uygulaması bildirim davranışı
Arka planda yerel oynatmayı desteklemeyen video veya ses uygulamaları, oynatmanın desteklenmediği durumlarda medya komutları göndermeyle ilgili sorunları önlemek için medya bildirimleri için belirli bir davranışa sahip olmalıdır:
- Medya yerel olarak oynatılırken ve uygulama ön plandayken medya bildirimini gönderin.
- Uygulama arka plandayken yerel oynatmayı duraklatın ve bildirimi kapatın.
- Uygulama ön plana geri döndüğünde yerel oynatma devam eder ve bildirim yeniden yayınlanır.
AndroidManifest.xml dosyasında Çıkış Değiştirici'yi etkinleştirme
Çıkış değiştiriciyi etkinleştirmek için MediaTransferReceiver
, uygulamanın AndroidManifest.xml
dosyasına eklenmelidir. Aksi takdirde özellik etkinleştirilmez ve uzaktan yerele özellik işareti de geçersiz olur.
<application>
...
<receiver
android:name="androidx.mediarouter.media.MediaTransferReceiver"
android:exported="true">
</receiver>
...
</application>
MediaTransferReceiver
, sistem kullanıcı arayüzü olan cihazlar arasında medya aktarımını sağlayan bir yayın alıcısıdır. Daha fazla bilgi için MediaTransferReceiver referansını inceleyin.
Yerelden uzaktan
Kullanıcı oynatmayı yerelden uzaktan oynatmaya geçirdiğinde Cast SDK'sı Cast oturumunu otomatik olarak başlatır. Ancak uygulamaların yerelden uzaktan yayına geçişi yönetmesi gerekir. Örneğin, yerel oynatmayı durdurup medyayı Cast cihazına yüklemelidir. Uygulamalar, onSessionStarted()
ve onSessionEnded()
geri çağırma işlevlerini kullanarak Cast SessionManagerListener
'i dinlemeli ve Cast SessionManager
geri çağırma işlevlerini aldığında işlemi gerçekleştirmelidir. Uygulamalar, Çıkış Değiştirici iletişim kutusu açıldığında ve uygulama ön planda olmadığında bu geri çağırmaların etkin kalmasını sağlamalıdır.
Arka planda yayınlama için SessionManagerListener'ı güncelleme
Eski Cast deneyimi, uygulama ön plandayken yerelden uzaktan yayını zaten destekliyor. Tipik bir Cast deneyimi, kullanıcılar uygulamadaki Cast simgesini tıklayıp medya aktarmak için bir cihaz seçtiğinde başlar. Bu durumda, uygulamanın onCreate()
veya onStart()
bölümünde SessionManagerListener
'e kaydolması ve uygulama etkinliğinin onStop()
veya onDestroy()
bölümünde dinleyicinin kaydını iptal etmesi gerekir.
Çıkış değiştiriciyi kullanarak yayınlama özelliğinin yeni deneyimiyle uygulamalar arka plandayken yayınlamaya başlayabilir. Bu özellik, özellikle arka planda oynatıldığında bildirim yayınlayan ses uygulamaları için kullanışlıdır. Uygulamalar, SessionManager
dinleyicilerini hizmetin onCreate()
bölümünde kaydedebilir ve hizmetin onDestroy()
bölümünden kaydını iptal edebilir. Uygulamalar, arka plandayken yerelden uzaktan geri çağırma çağrılarını (ör. onSessionStarted
) her zaman almalıdır.
Uygulama MediaBrowserService
kullanıyorsa SessionManagerListener
'i oraya kaydetmeniz önerilir.
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); } } }
Bu güncellemeyle birlikte, uygulama arka plandayken yerelden uzak cihaza aktarma işlemi geleneksel yayınlama işlemiyle aynı şekilde çalışır ve Bluetooth cihazlardan Cast cihazlara geçiş için ek işlem gerekmez.
Uzaktan yerele
Çıkış değiştirici, uzaktan oynatmayı telefon hoparlörüne veya yerel Bluetooth cihazına aktarma olanağı sunar. Bu özellik, CastOptions
üzerinde setRemoteToLocalEnabled
işaretini true
olarak ayarlayarak etkinleştirilebilir.
Mevcut gönderen cihazın birden fazla gönderenin bulunduğu mevcut bir oturuma katılması ve uygulamanın mevcut medyanın yerel olarak aktarılmasına izin verilip verilmediğini kontrol etmesi gereken durumlarda, uygulamalar SessionState
değerini kontrol etmek için SessionTransferCallback
onTransferred
geri çağırma işlevini kullanmalıdır.
setRemoteToLocalEnabled işaretini ayarlama
CastOptions.Builder
, etkin bir Yayınlama oturumu olduğunda Çıkış Değiştirici iletişim kutusunda telefon hoparlörünü ve yerel Bluetooth cihazlarını aktarma hedefleri olarak göstermek veya gizlemek için bir setRemoteToLocalEnabled
sağlar.
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() } }
Yerel olarak oynatmaya devam etme
Uzaktan yerele aktarımı destekleyen uygulamalar, medya aktarımına izin verilip verilmeyeceğini ve oynatmaya yerel olarak devam edilip edilemeyeceğini kontrol edebilmek için etkinlik gerçekleştiğinde bildirim almak üzere SessionTransferCallback
öğesini kaydetmelidir.
CastContext#addSessionTransferCallback(SessionTransferCallback)
, bir gönderen yerel oynatmaya aktarıldığında uygulamanın SessionTransferCallback
kaydetmesine ve onTransferred
ile onTransferFailed
geri çağırma çağrılarını dinlemesine olanak tanır.
Uygulama, SessionTransferCallback
kimliğinin kaydını iptal ettikten sonra artık SessionTransferCallback
almaz.
SessionTransferCallback
, mevcut SessionManagerListener
geri çağırmalarının bir uzantısıdır ve onSessionEnded
tetiklendikten sonra tetiklenir. Uzaktan yerele geri aramaların sırası:
onTransferring
onSessionEnding
onSessionEnded
onTransferred
Çıkış Değiştirici, uygulama arka plandayken ve yayın yaparken medya bildirim çipi tarafından açılabildiğinden, uygulamaların yerele aktarma işlemini arka planda oynatmayı destekleyip desteklemediklerine göre farklı şekilde ele alması gerekir. Aktarım başarısız olursa hata oluştuğunda onTransferFailed
tetiklenir.
Arka planda oynatmayı destekleyen uygulamalar
Arka planda oynatmayı destekleyen uygulamalar (genellikle ses uygulamaları) için Service
(ör. MediaBrowserService
) kullanılması önerilir. Hizmetler, onTransferred
geri çağırma işlevini dinlemeli ve oynatmayı hem uygulama ön plandayken hem de arka plandayken yerel olarak devam ettirmelidir.
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. } } }
Arka planda oynatmayı desteklemeyen uygulamalar
Arka planda oynatmayı desteklemeyen uygulamalarda (genellikle video uygulamaları) onTransferred
geri çağırma işlevini dinlemeniz ve uygulama ön plandaysa oynatmayı yerel olarak devam ettirmeniz önerilir.
Uygulama arka plandaysa oynatmayı duraklatmalı ve SessionState
'dan gerekli bilgileri (ör. medya meta verileri ve oynatma konumu) kaydetmelidir. Uygulama arka plandan ön plana getirildiğinde yerel oynatma, depolanan bilgilerle devam eder.
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. } } }
Uzaktan-uzaktan
Çıkış değiştirici, Akış Genişlemesi'ni kullanarak ses uygulamaları için birden fazla Cast özellikli hoparlör cihazına genişletmeyi destekler.
Ses uygulamaları, Google Cast SDK Geliştirici Konsolu'ndaki Alıcı Uygulaması ayarlarında Ses için Google Cast'i destekleyen uygulamalardır.
Hoparlörlerle akış genişletme
Çıkış Değiştirici'yi kullanan ses uygulamaları, Akış Genişlemesi'ni kullanarak Cast oturumu sırasında sesi birden fazla Cast özellikli hoparlör cihazına genişletebilir.
Bu özellik Cast platformu tarafından desteklenir ve uygulama varsayılan kullanıcı arayüzünü kullanıyorsa başka bir değişiklik gerekmez. Özel bir kullanıcı arayüzü kullanılıyorsa uygulama, kullanıcı arayüzünü bir gruba yayın yaptığını yansıtacak şekilde güncellemelidir.
Yayın genişletmesi sırasında yeni genişletilmiş grup adını almak için CastSession#addCastListener
simgesini kullanarak bir Cast.Listener
kaydedin.
Ardından, onDeviceNameChanged
geri arama sırasında CastSession#getCastDevice()
numaralı telefonu arayın.
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); } }
Uzaktan-uzaktan test etme
Özelliği test etmek için:
- İçeriğinizi geleneksel yayınlama veya yerelden uzak cihaza yayınlama özelliğini kullanarak Cast uyumlu bir cihaza yayınlayın.
- Giriş noktalarından birini kullanarak Çıkış Değiştirici'yi açın.
- Başka bir Cast uyumlu cihaza dokunduğunuzda ses uygulamaları içeriği ek cihaza genişleterek dinamik bir grup oluşturur.
- Cast uyumlu cihaza tekrar dokunun. Cihaz, dinamik gruptan kaldırılır.