Przełącznik wyjścia to funkcja pakietu SDK Cast, która umożliwia płynne przenoszenie
między lokalnym a zdalnym odtwarzaniem treści w Androidzie 13. Celem jest ułatwienie aplikacji nadawcy szybkiego i łatwego kontrolowania, gdzie odtwarzane są treści.
Przełącznik wyjścia używa
MediaRouter
do
przełączać odtwarzanie treści między głośnikiem telefonu, sparowanymi urządzeniami Bluetooth,
i zdalnych urządzeń obsługujących Cast. Przypadki użycia można podzielić na następujące kategorie:
scenariusze:
Pobierz i użyj przykładowej aplikacji CastVideo na Androida. .
Przełącznik wyjścia powinien być włączony, aby obsługiwać przełączanie z lokalnego na zdalne, z lokalnego na zdalne i z zdalnego na zdalne. Aby to zrobić, wykonaj czynności opisane w tym przewodniku. Brak dodatkowe czynności wymagane do przeniesienia między urządzeniem lokalnym głośnikach i sparowanych urządzeniach Bluetooth.
Interfejs przełącznika wyjścia
Przełącznik wyjścia wyświetla dostępne urządzenia lokalne i zdalne, a także ich stan, w tym czy urządzenie jest wybrane, czy łączy się z komputerem oraz aktualny poziom głośności. Jeśli oprócz nich istnieją inne urządzenia na bieżące urządzenie, kliknięcie innego urządzenia umożliwia przeniesienie multimediów na wybranym urządzeniu.
Znane problemy
- Sesje multimediów utworzone na potrzeby odtwarzania lokalnego zostaną zamknięte i powtórnie utworzone, gdy przełączysz się na powiadomienie pakietu SDK Cast.
Punkty wejścia
Powiadomienie o multimediach
Jeśli aplikacja opublikuje powiadomienie o multimediach z oznaczeniem
MediaSession
za
odtwarzanie lokalne (odtwarzanie lokalnie) w prawym górnym rogu powiadomienia o multimediach
wyświetla powiadomienie z nazwą urządzenia (np. głośnikem telefonu),
treści, które są aktualnie odtwarzane. Kliknięcie elementu powiadomienia otwiera się
w interfejsie systemowego okna przełączania wyjścia.
Ustawienia głośności
Interfejs systemu okna przełączania wyjścia można również aktywować, klikając fizyczny przycisk głośności na urządzeniu, kliknij ikonę ustawień na dole i kliknij przycisk „Włącz <nazwa aplikacji>” na <urządzeniu przesyłającym> tekstu.
Podsumowanie kroków
- Upewnij się, że spełnione są wymagania wstępne
- Włącz przełącznik wyjścia w pliku AndroidManifest.xml
- Aktualizowanie usługi SessionManagerListener do przesyłania w tle
- Dodanie obsługi funkcji Zdalne do zdalnego
- Ustaw flagę setRemoteToLocalEnabled
- Kontynuuj odtwarzanie lokalnie
Wymagania wstępne
- Przeprowadź migrację istniejącej aplikacji na Androida na AndroidaX.
- Zaktualizuj aplikację
build.gradle
, aby używać minimalnej wymaganej wersji Pakiet Android Sender SDK na potrzeby przełącznika wyjścia:dependencies { ... implementation 'com.google.android.gms:play-services-cast-framework:21.2.0' ... }
- Aplikacja obsługuje powiadomienia o multimediach.
- Urządzenie z Androidem 13.
Skonfiguruj powiadomienia o multimediach
Aby użyć przełącznika wyjścia,
audio oraz
aplikacje wideo
są wymagane do utworzenia powiadomienia o multimediach, w którym będzie wyświetlany stan odtwarzania
elementów sterujących ich multimediami do lokalnego odtwarzania. Wymaga to utworzenia
MediaSession
ustawianie
MediaStyle
z tokenem MediaSession
i ustawić opcje sterowania multimediami na
powiadomienia.
Jeśli nie używasz obecnie kodu MediaStyle
ani MediaSession
, fragment kodu
poniżej znajdziesz wskazówki, jak je skonfigurować. Dostępne są też przewodniki po konfiguracji multimediów.
wywołania zwrotne sesji dla
audio oraz
film
Aplikacje:
// 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(); }
Aby dodać w powiadomieniu informacje o multimediach,
musisz dodać pliki multimedialne
metadane i stan odtwarzania,
do: MediaSession
.
Aby dodać metadane do obiektu MediaSession
, użyj
setMetaData()
.
i dostarczyć wszystkie
Stałe MediaMetadata
dla
Twoich multimediów na
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() ); }
Aby dodać stan odtwarzania do MediaSession
, użyj setPlaybackState()
i podaj wszystkie odpowiednie stałe PlaybackStateCompat
dla multimediów w 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() ); }
Zachowanie powiadomień z aplikacji wideo
Aplikacje wideo lub audio, które nie obsługują odtwarzania lokalnego w tle. powinno działać w specjalny sposób w przypadku powiadomień o multimediach, co pozwala uniknąć problemów wysyłanie poleceń multimedialnych w sytuacjach, gdy odtwarzanie nie jest obsługiwane:
- Publikuj powiadomienie o multimediach podczas lokalnego odtwarzania treści i w aplikacji na pierwszym planie.
- Wstrzymaj odtwarzanie lokalne i zamknij powiadomienie, gdy aplikacja będzie w w tle.
- Gdy aplikacja wróci na pierwszy plan, odtwarzanie lokalne powinno zostać wznowione powiadomienie powinno zostać opublikowane ponownie.
Włączanie przełącznika wyjścia w pliku AndroidManifest.xml
Aby włączyć przełącznik wyjścia,
MediaTransferReceiver
należy dodać do usługi AndroidManifest.xml
aplikacji. W przeciwnym razie funkcja
nie zostanie włączona, a flaga funkcji „zdalnie do lokalnego miejsca” również będzie nieprawidłowa.
<application>
...
<receiver
android:name="androidx.mediarouter.media.MediaTransferReceiver"
android:exported="true">
</receiver>
...
</application>
MediaTransferReceiver
to odbiornik, który umożliwia przesyłanie multimediów między urządzeniami
Interfejs. Więcej informacji znajdziesz w dokumentacji MediaTransferReceiver.
Z komputera na zdalny
Gdy użytkownik przełączy odtwarzanie z lokalnego na zdalne, pakiet SDK Cast uruchomi się
automatycznie rozpocząć sesję przesyłania. Aplikacje muszą jednak obsługiwać przechodzenie
z lokalnego na zdalny, na przykład zatrzymaj odtwarzanie lokalne
i załaduje multimedia na urządzenie przesyłające. Aplikacje powinny nasłuchiwać wywołań zwrotnych
SessionManagerListener
i onSessionStarted()
onSessionEnded()
oraz obsługiwać działanie po otrzymaniu wywołań zwrotnych
SessionManager
. Aplikacje powinny pilnować, aby wywołania zwrotne były nadal aktywne,
Otwarte jest okno przełączania danych wyjściowych, a aplikacja nie działa na pierwszym planie.
Aktualizacja interfejsu SessionManagerListener na potrzeby przesyłania w tle
Starsza wersja Cast obsługuje już połączenie lokalne do zdalnego, gdy aplikacja
na pierwszym planie. Typowa funkcja Cast uruchamia się, gdy użytkownik kliknie ikonę Przesyłaj
w aplikacji i wybierz urządzenie, na którym chcesz odtwarzać multimedia. W tym przypadku aplikacja musi zarejestrować się w SessionManagerListener
,
w onCreate()
lub
onStart()
oraz zarejestrować detektor w onStop()
lub
onDestroy()
aktywności aplikacji.
Dzięki nowej funkcji przesyłania za pomocą przełącznika wyjścia aplikacje mogą uruchamiać się
przesyłać nawet w tle. Jest to szczególnie przydatne w przypadku reklam dźwiękowych
aplikacje publikujące powiadomienia podczas odtwarzania w tle. Aplikacje mogą się rejestrować
SessionManager
detektorów w onCreate()
usługi i wyrejestruj się z onDestroy()
usługi. Aplikacje zawsze powinny otrzymywać wywołania zwrotne dla połączenia lokalnego (np.
jako onSessionStarted
)
gdy aplikacja działa w tle.
Jeśli aplikacja używa
MediaBrowserService
zalecamy zarejestrowanie SessionManagerListener
tam.
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); } } }
Dzięki tej aktualizacji funkcja przesyłania z urządzenia lokalnego na urządzenie zdalne działa tak samo jak zwykłe przesyłanie, gdy aplikacja jest w tle. Nie trzeba też wykonywać dodatkowych czynności, aby przełączyć się z urządzeń Bluetooth na urządzenia z Chromecastem.
Zdalnie do lokalnego
Przełącznik wyjścia umożliwia przełączanie sygnału odtwarzania ze zdalnego odtwarzania na
głośniku telefonu lub lokalnego urządzenia Bluetooth. Aby włączyć tę funkcję, ustaw
setRemoteToLocalEnabled
flagę do true
w CastOptions
.
W przypadku, gdy urządzenie wysyłające dołącza istniejącą sesję z
wielu nadawców, a aplikacja musi sprawdzić, czy bieżące multimedia mogą
zostaną przeniesione lokalnie, aplikacje powinny używać: onTransferred
wywołanie zwrotne SessionTransferCallback
aby sprawdzić SessionState
.
Ustawianie flagi setRemoteToLocalEnabled
CastOptions.Builder
pozwala setRemoteToLocalEnabled
wyświetlać lub ukrywać głośnik telefonu i lokalne urządzenia Bluetooth jako cele przesyłania w oknie przełącznika wyjścia podczas aktywnej sesji przesyłania.
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() } }
Kontynuowanie odtwarzania lokalnie
Aplikacje, które obsługują przesyłanie z dalszego urządzenia na lokalne, powinny zarejestrować SessionTransferCallback
, aby otrzymywać powiadomienia o wystąpieniu zdarzenia. Dzięki temu mogą sprawdzić, czy należy zezwolić na przeniesienie treści i kontynuowanie odtwarzania lokalnie.
CastContext#addSessionTransferCallback(SessionTransferCallback)
pozwala aplikacji zarejestrować swoje SessionTransferCallback
i nasłuchiwać wywołań zwrotnych onTransferred
i onTransferFailed
, gdy nadawca
przeniesione do lokalnego odtwarzania.
Gdy aplikacja zarejestruje SessionTransferCallback
, przestanie otrzymywać SessionTransferCallback
.
SessionTransferCallback
to rozszerzenie istniejących wywołań zwrotnych SessionManagerListener
, które jest wywoływane po wywołaniu onSessionEnded
. Kolejność wywołań zwrotnych z urządzenia zdalnego na urządzenie lokalne jest następująca:
onTransferring
onSessionEnding
onSessionEnded
onTransferred
Ponieważ przełącznik wyjścia może być otwierany przez element powiadomień o multimediach, gdy
aplikacja działa w tle i przesyła treści, aplikacje muszą obsługiwać przenoszenie na lokalne.
różni się w zależności od tego, czy obsługują odtwarzanie w tle, czy nie. W przypadku nieudanego transferu funkcja onTransferFailed
zostanie wywołana w dowolnym momencie, gdy wystąpi błąd.
Aplikacje obsługujące odtwarzanie w tle
W przypadku aplikacji, które obsługują odtwarzanie w tle (zwykle są to aplikacje audio),
zalecamy użycie właściwości Service
(np. MediaBrowserService
). Usługi
powinien posłuchać: onTransferred
wywołanie zwrotne i wznowienie odtwarzania lokalnie zarówno wtedy, gdy aplikacja działa na pierwszym planie, jak i wtedy, gdy aplikacja działa na pierwszym planie,
w tle.
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. } } }
Aplikacje, które nie obsługują odtwarzania w tle
W przypadku aplikacji, które nie obsługują odtwarzania w tle (zwykle aplikacji wideo),
polecam posłuchać: onTransferred
wywołanie zwrotne i wznowienie odtwarzania lokalnie, jeśli aplikacja działa na pierwszym planie.
Jeśli aplikacja działa w tle, powinna wstrzymać odtwarzanie i zapisać
niezbędne informacje od: SessionState
(na przykład metadane multimediów i pozycja odtwarzania). Gdy aplikacja jest
na pierwszym planie tła, odtwarzanie lokalne powinno być kontynuowane
przechowywane informacje.
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. } } }
Zdalnie-zdalnie
Przełącznik wyjścia umożliwia rozszerzenie na wiele urządzeń obsługujących Cast. na potrzeby aplikacji audio korzystających z rozszerzania strumienia.
Aplikacje audio to aplikacje, które obsługują Google Cast for Audio w aplikacji odbiornik w ustawieniach Google Cast SDK. Konsola
Zwiększanie zasięgu transmisji za pomocą głośników
Aplikacje audio korzystające z przełącznika wyjścia mogą rozszerzać dźwięk. na wielu głośnikach obsługujących Cast podczas sesji przesyłania za pomocą opcji Prześlij strumieniowo Rozszerzanie.
Ta funkcja jest obsługiwana przez platformę Cast i nie wymaga żadnych dodatkowych funkcji. zmienia się, jeśli aplikacja używa domyślnego interfejsu użytkownika. Jeśli korzystasz z niestandardowego interfejsu, aplikacja należy zaktualizować interfejs, aby odzwierciedlał, że aplikacja przesyła do grupy.
Aby otrzymać nową nazwę rozwiniętej grupy podczas rozwijania strumienia:
zarejestruj
Cast.Listener
za pomocą
CastSession#addCastListener
Następnie zadzwoń
CastSession#getCastDevice()
podczas wywołania zwrotnego onDeviceNameChanged
.
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); } }
Testowanie połączeń zdalnych
Aby przetestować tę funkcję:
- Przesyłaj treści na urządzenie obsługujące Cast za pomocą konwencjonalnego lub za pomocą: local-to-remote.
- Otwórz przełącznik wyjścia, używając jednego z punktów wejścia.
- Kliknij inne urządzenie obsługujące Cast. Aplikacje audio rozwiną treści na urządzenia dodatkowego, tworząc grupę dynamiczną.
- Ponownie kliknij urządzenie obsługujące Google Cast. Zostanie ono usunięte z dynamicznej sceny. grupy reklam.