Çıkış Değiştirici

Çıkış Değiştirici, Cast SDK'nın sorunsuz aktarıma olanak tanıyan bir özelliğidir. yerel ve uzaktan oynatma arasında geçiş yapıyor. Hedef , gönderen uygulamalarının içeriğin nerede oynatılacağını kolay ve hızlı bir şekilde kontrol etmesine yardımcı olmaktır. Çıkış Değiştirici, MediaRouter kitaplığını içerik oynatımını telefon hoparlöründe, eşlenen Bluetooth cihazlarda ve ve Cast uyumlu uzak cihazlar. Kullanım alanları aşağıdaki kategorilere ayrılabilir senaryolar:

Yerelden uzaktan kumandaya, uzaktan kumandadan yerele geçiş desteği için Çıkış Değiştirici etkinleştirilmelidir uzaktan kumandaya geçişini yapabilirsiniz. Hayır, yerel cihaz arasında aktarımı desteklemek için gereken ek adımlar hoparlörler ve eşlenen Bluetooth cihazlar.

Çıkış Değiştirici Kullanıcı Arayüzü

Çıkış Değiştirici, mevcut olan yerel ve uzak cihazları görüntüler seçili olup olmadığı gibi mevcut cihaz durumlarını da bağlanıyor. Bu, geçerli ses seviyesidir. Ek olarak başka cihazlar da Geçerli cihaza, diğer cihazı tıkladığınızda medya içeriklerini seçilen cihazda oynatın.

Bilinen sorunlar

  • Yerel oynatma için oluşturulan Medya Oturumları kapatılır ve yeniden oluşturulur geçiş yapıldığından emin olun.

Giriş noktaları

Medya bildirimi

Bir uygulama Şunun için MediaSession: yerel oynatma (yerel olarak oynatma), medya bildiriminin sağ üst köşesinde bu cihazın adını belirten bir bildirim çipi görüntüler (ör. telefon hoparlörü) içerik şu anda oynatılıyor. Bildirim çipine dokunduğunuzda açılır iletişim kutusu sistem kullanıcı arayüzü.

Ses düzeyi ayarları

Çıkış Değiştirici iletişim kutusunun sistem kullanıcı arayüzü, cihazın alt kısmındaki ayarlar simgesine dokunarak, "<App Name> adlı uygulamayı oynat"a dokunun <Yayın Cihazı> üzerinde" metin.

Adımların özeti

Ön koşullar

  1. Mevcut Android uygulamanızı AndroidX'e taşıyın.
  2. build.gradle Çıkış Değiştirici için Android Gönderen SDK'sı:
    dependencies {
      ...
      implementation 'com.google.android.gms:play-services-cast-framework:21.2.0'
      ...
    }
  3. Uygulama, medya bildirimlerini destekliyor.
  4. Android 13 çalıştıran cihaz.

Medya Bildirimleri'ni ayarlayın

Çıkış Değiştirici'yi kullanmak için audio ve video uygulamaları oynatma durumunu görüntülemek ve görüntülemek için bir medya bildirimi oluşturmak yerel oynatma için medya denetimlerine sahiptir. Bu, bir MediaSession, ayarlamak MediaStyle MediaSession jetonu kullanılarak ve bildirimi görürsünüz.

Şu anda bir MediaStyle ve MediaSession kullanmıyorsanız snippet, aşağıda bunların nasıl ayarlanacağı gösterilmiştir. Medyanın kurulumu için kılavuzlar mevcuttur şunun için oturum geri çağırmaları: audio ve video uygulamalar:

Kotlin
// 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)
Java
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 medya öğelerinizi eklemeniz meta veriler ve oynatma durumu - MediaSession.

MediaSession öğesine meta veri eklemek için şunu kullanın: setMetaData() ve ilgili tüm bilgileri MediaMetadata sabitleri içeriklerinizin MediaMetadataCompat.Builder()

Kotlin
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()
)
Java
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 içine eklemek üzere şunu kullanın: setPlaybackState() ve ilgili tüm bilgileri PlaybackStateCompat değerleri, PlaybackStateCompat.Builder()

Kotlin
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()
)
Java
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 oynatma özelliğini desteklemeyen video uygulamaları veya ses uygulamaları ile ilgili sorunlardan kaçınmak için medya bildirimlerinde belirli bir davranışa sahip olmalıdır. oynatmanın desteklenmediği durumlarda medya komutları gönderme:

  • Yerel olarak medya oynatırken ve uygulama açıkken medya bildirimini yayınla görebilirsiniz.
  • Uygulama şu programdayken yerel oynatmayı duraklatın ve bildirimi kapatın arka plan.
  • Uygulama ön plana geri döndüğünde yerel oynatma devam eder ve bildirim yeniden yayınlanır.

AndroidManifest.xml dosyasında Çıkış Değiştiriciyi etkinleştir

Çıkış Değiştirici'yi etkinleştirmek için MediaTransferReceiver uygulamanın AndroidManifest.xml öğesine eklenmesi gerekiyor. Seçili değilse özellik etkinleştirilmeyecek ve uzaktan yerele özellik bayrağı da geçersiz olacaktır.

<application>
    ...
    <receiver
         android:name="androidx.mediarouter.media.MediaTransferReceiver"
         android:exported="true">
    </receiver>
    ...
</application>

İlgili içeriği oluşturmak için kullanılan MediaTransferReceiver Sisteme sahip cihazlar arasında medya aktarımını sağlayan bir yayın alıcıdır Kullanıcı arayüzü. Bkz. MediaTransferReceiver referans konulu videomuzu izleyin.

Yerelden Uzaktan Kumandaya

Kullanıcı oynatma işlemini yerel moddan uzaktan kumanda olarak değiştirdiğinde Cast SDK'sı başlar otomatik olarak değiştirebilirsiniz. Ancak, uygulamaların yerel çalmayı durdurun, örneğin yerel oynatmayı durdurun yayın cihazına yükleyin. Uygulamalar Cast'i dinlemelidir SessionManagerListener, her bir arama terimi için onSessionStarted() ve onSessionEnded() ve Cast alınırken işlemi işleme SessionManager daha fazla bilgi edindiniz. Uygulamalar, Çıkış Değiştirici iletişim kutusu açılır ve uygulama ön planda değildir.

Arka planda yayınlama için SessionManagerListener'ı güncelleme

Uygulama şu durumda olduğunda eski Cast deneyimi yerelden uzaktan kumandaya desteği zaten destekliyor: ön planda çalışır. Tipik bir Cast deneyimi, kullanıcılar Yayınla simgesini tıkladığında başlar dokunun ve medya akışı gerçekleştireceğiniz bir cihaz seçin. Bu durumda, uygulamanın şuna kaydol: SessionManagerListener, onCreate() veya onStart() ve dinleyicinin kaydını onStop() veya onDestroy() olduğunu görebilirsiniz.

Çıkış Değiştirici'yi kullanarak yayınlama olanağı sunan yeni deneyim sayesinde uygulamalar arka planda çalışırken yayın yapabilir. Bu, özellikle seslendirmede arka planda oynatırken bildirim yayınlayan uygulamalar. Uygulamalar kaydolabilir SessionManager işleyicileri hizmet onCreate()'inde iptal edebilir ve onDestroy() hizmetindeki kaydınızı iptal edebilirsiniz. olabilir. Uygulamalar her zaman yerelden uzaktan geri çağırmaları (ör. onSessionStarted olarak) arka planda çalışıyor.

Uygulama MediaBrowserService, SessionManagerListener inceleyeceğiz.

Kotlin
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)
        }
    }
}
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, yerelden uzaktan kumandaya geleneksel yayın işlevi aynı şekilde çalışır. arka planda olduğundan Google'ın uygulama paketinden geçiş yapmak için Bluetooth cihazlardan yayın cihazlarına

Uzaktan yerele

Çıkış Değiştirici, uzaktan oynatmadan cihaza telefonun hoparlöründen veya yerel Bluetooth cihazından. Bu özellik, setRemoteToLocalEnabled CastOptions üzerinde true olarak işaretle.

Mevcut bir gönderen cihazın, mevcut bir oturuma göndericinin mevcut medyaya izin verilip verilmediğini yerel olarak aktarıldığında, uygulamalar onTransferred SessionTransferCallback aramasının geri araması SessionState simgesini kontrol edin.

setRemoteToLocalEnabled işaretini ayarlama

CastOptions.Builder Telefon hoparlörünü ve yerel Bluetooth cihazları aktarım yapılacak şekilde göstermek veya gizlemek için bir setRemoteToLocalEnabled sağlar iletişim kutusu görüntülenir.

Kotlin
class CastOptionsProvider : OptionsProvider {
    fun getCastOptions(context: Context?): CastOptions {
        ...
        return Builder()
            ...
            .setRemoteToLocalEnabled(true)
            .build()
    }
}
Java
public class CastOptionsProvider implements OptionsProvider {
    @Override
    public CastOptions getCastOptions(Context context) {
        ...
        return new CastOptions.Builder()
            ...
            .setRemoteToLocalEnabled(true)
            .build()
  }
}

Oynatmaya yerel olarak devam et

Uzaktan yerele geçiş özelliğini destekleyen uygulamalar SessionTransferCallback cihazını kaydetmelidir. Böylece, etkinlik gerçekleştiğinde bildirim alarak medyanın yayınlanıp yayınlanmayacağını kontrol edebilirler aktarmasına ve yerel olarak oynatmaya devam etmesine izin verildi.

CastContext#addSessionTransferCallback(SessionTransferCallback) bir uygulamanın kendi SessionTransferCallback cihazını kaydetmesine izin verir ve bir gönderen şu olduğunda onTransferred ve onTransferFailed geri çağırmalarını dinleyebilirsiniz. yerel oynatmaya aktarıldı.

Uygulama, SessionTransferCallback kaydını iptal ettikten sonra, Uygulama artık SessionTransferCallback almayacak sn.

SessionTransferCallback , mevcut SessionManagerListener geri çağırmalar ve onSessionEnded tetiklendikten sonra tetiklenir. Sıra, uzaktan yerele geri çağırma:

  1. onTransferring
  2. onSessionEnding
  3. onSessionEnded
  4. onTransferred

Çıkış Değiştirici, Uygulama arka planda ve yayın yapıyor, uygulamaların yerel cihaza aktarımı yapması gerekir arka planda oynatmayı destekleyip desteklememelerine bağlı olarak farklılık gösterebilir. Bu durumda (başarısız transfer), onTransferFailed etkinleştiği her an etkinleşir.

Arka planda oynatmayı destekleyen uygulamalar

Arka planda oynatmayı destekleyen uygulamalarda (genellikle ses uygulamaları) Service (örneğin MediaBrowserService) kullanılması önerilir. Hizmetler onTransferred dinlemeli uygulama ön plandayken geri çağırma olanağı ve oynatmaya yerel olarak devam etme arka plan.

Kotlin
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.
        }
    }
}
Java
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 uygulamalar için (genellikle video uygulamaları) onTransferrednı dinlemeniz önerilir Uygulama ön plandaysa geri çağırma olanağı ve yerel olarak oynatmaya devam etme olanağı tanır.

Uygulama arka plandaysa oynatmayı duraklatır ve SessionState tarafından sağlanan, (örneğin, medya meta verileri ve oynatma konumu). Uygulama: yerel oynatma şununla devam etmelidir: saklı tutar.

Kotlin
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.
        }
    }
}
Java
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 kumandaya

Çıkış Değiştirici, Cast uyumlu birden fazla ekrana genişletme özelliğini destekler Ses Uygulamaları için Yayın Genişletme özelliğini kullanan hoparlör cihazları

Ses uygulamaları, Alıcı Uygulaması'nda Google Cast'i destekleyen uygulamalardır. Google Cast SDK'sı Geliştiricisindeki ayarlar Konsol

Hoparlörlerle Yayın Genişletme

Çıkış Değiştirici'yi kullanan ses uygulamaları, sesi genişletebilir. aktarma özelliğini kullanan bir yayın oturumu sırasında Cast uyumlu birden fazla hoparlöre Genişletme.

Bu özellik, Cast platformu tarafından desteklenir ve başka herhangi bir işlem gerektirmez uygulama varsayılan kullanıcı arayüzünü kullanıyorsa değişir. Özel bir kullanıcı arayüzü kullanılıyorsa uygulama kullanıcı arayüzünü, uygulamanın bir gruba yayın yaptığını yansıtacak şekilde güncellemelidir.

Akış genişletme sırasında yeni genişletilmiş grup adını almak için bir kaydettirmek Cast.Listener her bir arama terimi için CastSession#addCastListener. Ardından şu numarayı arayın: CastSession#getCastDevice() onDeviceNameChanged geri araması sırasında.

Kotlin
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)
    }
}
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 kumandaya test etme

Özelliği test etmek için:

  1. İçeriğinizi Cast uyumlu bir cihazda yayınlamak için geleneksel yayınlama yöntemini veya local-to-remote'dır.
  2. Giriş noktalarından birini kullanarak Çıkış Değiştirici'yi açın.
  3. Cast uyumlu başka bir cihaza dokunun. Ses uygulamaları, içeriği ek cihaz, dinamik bir grup oluşturuyor.
  4. Cast uyumlu cihaza tekrar dokunun. Cihaz dinamikten kaldırılır. grubu.