出力スイッチャーは、シームレスな転送を可能にする Cast SDK の機能です。
コンテンツのローカル再生とリモート再生の違い(Android 13 以降)目標
送信側アプリでコンテンツの再生先を簡単かつ迅速に制御できるようにすることです。
Output Switcher は MediaRouter
ライブラリを使用して、スマートフォンのスピーカー、ペア設定された Bluetooth デバイス、リモートの Cast 対応デバイス間でコンテンツの再生を切り替えます。ユースケースは次のように分類できます。
シナリオ:
CastVideos-android サンプルアプリをダウンロードして使用する をご覧ください。
ローカルからリモート、リモートからローカルをサポートするには、出力スイッチャーを有効にする必要があります リモートからリモートへの移動を 制御することもできます現在、 ローカル デバイス間の転送をサポートするために必要となる追加の手順 ペア設定した Bluetooth デバイスに接続できます。
出力スイッチャー UI
出力スイッチャーには、使用可能なローカル デバイスとリモート デバイスが表示されます。 現在のデバイスの状態(デバイスが選択されているかどうかなど) 現在の音量レベルが表示されます。現在のデバイス以外に他のデバイスがある場合は、[他のデバイス] をクリックして、選択したデバイスにメディアの再生を転送できます。
既知の問題
- ローカル再生用に作成されたメディア セッションは破棄され、再作成されます 」が表示されます。
エントリ ポイント
メディアに関する通知
アプリから投稿されたメディア通知を
MediaSession
:
ローカル再生(ローカルでの再生中)、メディア通知の右上
通知チップにそのデバイス名(スマートフォンのスピーカーなど)が
。通知チップをタップすると開く
[Output Switcher] ダイアログのシステム UI。
音量の設定
出力切り替えダイアログ システム UI は、デバイスの物理的な音量ボタンをクリックし、下部にある設定アイコンをタップして、[<アプリ名> を <キャスト デバイス> で再生] テキストをタップすることでもトリガーできます。
ステップの概要
- 前提条件を満たしていることを確認する
- AndroidManifest.xml で出力スイッチャーを有効にする
- バックグラウンド キャスト用の SessionManagerListener を更新
- リモート間接リモートのサポートを追加
- setRemoteToLocalEnabled フラグを設定する
- ローカルでの再生を続行
前提条件
- 既存の Android アプリを AndroidX に移行します。
- 必要最小限のバージョンのバージョンのものを使用するには、アプリの
build.gradle
を更新してください 出力スイッチャー用の Android Sender SDK:dependencies { ... implementation 'com.google.android.gms:play-services-cast-framework:21.2.0' ... }
- アプリがメディア通知をサポートしている。
- Android 13 を搭載したデバイス。
メディア通知の設定
出力スイッチャーを使用するには
audio と
動画アプリ
再生ステータスを表示するメディア通知を作成し、
ローカル再生のメディア コントロールを設定できます。そのためには、Terraform で
MediaSession
「
MediaStyle
MediaSession
のトークンを使用し、メディア コントロールを
通知を受け取ります。
現在 MediaStyle
と MediaSession
を使用していない場合は、スニペットは
以下に、設定方法と、メディアの設定に関するガイドを示します。
セッション コールバックを
audio と
動画
アプリ:
// Create a media session. NotificationCompat.MediaStyle // PlayerService is your own Service or Activity responsible for media playback. val mediaSession = MediaSessionCompat(this, "PlayerService") // Create a MediaStyle object and supply your media session token to it. val mediaStyle = Notification.MediaStyle().setMediaSession(mediaSession.sessionToken) // Create a Notification which is styled by your MediaStyle object. // This connects your media session to the media controls. // Don't forget to include a small icon. val notification = Notification.Builder(this@PlayerService, CHANNEL_ID) .setStyle(mediaStyle) .setSmallIcon(R.drawable.ic_app_logo) .build() // Specify any actions which your users can perform, such as pausing and skipping to the next track. val pauseAction: Notification.Action = Notification.Action.Builder( pauseIcon, "Pause", pauseIntent ).build() notification.addAction(pauseAction)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { // Create a media session. NotificationCompat.MediaStyle // PlayerService is your own Service or Activity responsible for media playback. MediaSession mediaSession = new MediaSession(this, "PlayerService"); // Create a MediaStyle object and supply your media session token to it. Notification.MediaStyle mediaStyle = new Notification.MediaStyle().setMediaSession(mediaSession.getSessionToken()); // Specify any actions which your users can perform, such as pausing and skipping to the next track. Notification.Action pauseAction = Notification.Action.Builder(pauseIcon, "Pause", pauseIntent).build(); // Create a Notification which is styled by your MediaStyle object. // This connects your media session to the media controls. // Don't forget to include a small icon. String CHANNEL_ID = "CHANNEL_ID"; Notification notification = new Notification.Builder(this, CHANNEL_ID) .setStyle(mediaStyle) .setSmallIcon(R.drawable.ic_app_logo) .addAction(pauseAction) .build(); }
通知にメディアの情報を入力するには、次の操作を行います。
既存のメディアの
メタデータと再生状態
MediaSession
に送信します。
MediaSession
にメタデータを追加するには、次のコマンドを使用します。
setMetaData()
関連するすべてのアラートと
次の MediaMetadata
定数:
自分のメディアを
MediaMetadataCompat.Builder()
。
mediaSession.setMetadata(MediaMetadataCompat.Builder() // Title .putString(MediaMetadata.METADATA_KEY_TITLE, currentTrack.title) // Artist // Could also be the channel name or TV series. .putString(MediaMetadata.METADATA_KEY_ARTIST, currentTrack.artist) // Album art // Could also be a screenshot or hero image for video content // The URI scheme needs to be "content", "file", or "android.resource". .putString( MediaMetadata.METADATA_KEY_ALBUM_ART_URI, currentTrack.albumArtUri) ) // Duration // If duration isn't set, such as for live broadcasts, then the progress // indicator won't be shown on the seekbar. .putLong(MediaMetadata.METADATA_KEY_DURATION, currentTrack.duration) .build() )
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { mediaSession.setMetadata( new MediaMetadataCompat.Builder() // Title .putString(MediaMetadata.METADATA_KEY_TITLE, currentTrack.title) // Artist // Could also be the channel name or TV series. .putString(MediaMetadata.METADATA_KEY_ARTIST, currentTrack.artist) // Album art // Could also be a screenshot or hero image for video content // The URI scheme needs to be "content", "file", or "android.resource". .putString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI, currentTrack.albumArtUri) // Duration // If duration isn't set, such as for live broadcasts, then the progress // indicator won't be shown on the seekbar. .putLong(MediaMetadata.METADATA_KEY_DURATION, currentTrack.duration) .build() ); }
再生状態を MediaSession
に追加するには、次のコマンドを使用します。
setPlaybackState()
関連するすべてのアラートと
PlaybackStateCompat
定数を
PlaybackStateCompat.Builder()
。
mediaSession.setPlaybackState( PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, // Playback position // Used to update the elapsed time and the progress bar. mediaPlayer.currentPosition.toLong(), // Playback speed // Determines the rate at which the elapsed time changes. playbackSpeed ) // isSeekable // Adding the SEEK_TO action indicates that seeking is supported // and makes the seekbar position marker draggable. If this is not // supplied seek will be disabled but progress will still be shown. .setActions(PlaybackStateCompat.ACTION_SEEK_TO) .build() )
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { mediaSession.setPlaybackState( new PlaybackStateCompat.Builder() .setState( PlaybackStateCompat.STATE_PLAYING, // Playback position // Used to update the elapsed time and the progress bar. mediaPlayer.currentPosition.toLong(), // Playback speed // Determines the rate at which the elapsed time changes. playbackSpeed ) // isSeekable // Adding the SEEK_TO action indicates that seeking is supported // and makes the seekbar position marker draggable. If this is not // supplied seek will be disabled but progress will still be shown. .setActions(PlaybackStateCompat.ACTION_SEEK_TO) .build() ); }
動画アプリの通知動作
バックグラウンドでのローカル再生に対応していない動画アプリやオーディオ アプリ 特定の動作をするよう、メディア通知の動作を 再生がサポートされていない状況でメディア コマンドを送信する
- アプリがローカルで再生されているときにメディア通知を送信する 使用できます。
- ローカル再生を一時停止し、アプリが 説明します。
- アプリがフォアグラウンドに戻ったら、ローカル再生を再開し、 通知を再投稿する必要があります。
AndroidManifest.xml で出力スイッチャーを有効にする
出力スイッチャーを有効にするには、
MediaTransferReceiver
アプリの AndroidManifest.xml
に追加する必要があります。そうでない場合、この機能は
無効になり、remote-to-local 機能フラグも無効になります。
<application>
...
<receiver
android:name="androidx.mediarouter.media.MediaTransferReceiver"
android:exported="true">
</receiver>
...
</application>
「
MediaTransferReceiver
システムとデバイス間のメディア転送を可能にするブロードキャスト レシーバです。
UI です。詳しくは、MediaTransferReceiver
リファレンス
をご覧ください。
ローカルからリモート
再生をローカルからリモートに切り替えると、Cast SDK が起動します
自動的にキャスト セッションが削除されます。ただし、アプリは移行元のプラットフォームから
ローカルからリモートへ(たとえば、ローカルの再生を停止する)
キャスト デバイスにメディアを読み込みます。アプリは、onSessionStarted()
コールバックと onSessionEnded()
コールバックを使用して Cast SessionManagerListener
をリッスンし、Cast SessionManager
コールバックを受信したときにアクションを処理する必要があります。アプリはこれらのコールバックが有効な状態で
Output Switcher ダイアログが開いており、アプリがフォアグラウンドではない。
バックグラウンド キャスト用の SessionManagerListener を更新
従来のキャストでは、アプリが
がフォアグラウンドにあります。通常のキャスト エクスペリエンスは、ユーザーがキャスト アイコンをクリックすると開始されます。
をタップし、メディアをストリーミングするデバイスを選択します。この場合、アプリは
Google Cloud コンソールで
SessionManagerListener
場所: onCreate()
、または
onStart()
リスナーの登録を解除し、
onStop()
または
onDestroy()
追跡します。
出力スイッチャーを使用した新しいキャスト機能により、
バックグラウンドでの
キャストが可能です。これは特に、音声や動画などの
バックグラウンドでの再生中に通知を送信するアプリ。アプリは登録が可能
SessionManager
サービスの onCreate()
でリスナーを設定し、onDestroy()
で登録を解除する
構成されます。アプリは常にローカルからリモートへのコールバック(
onSessionStarted
)
アプリがバックグラウンドで動作しているとき。
アプリが
MediaBrowserService
SessionManagerListener
を登録することをおすすめします。
できます。
class MyService : Service() { private var castContext: CastContext? = null protected fun onCreate() { castContext = CastContext.getSharedInstance(this) castContext .getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession::class.java) } protected fun onDestroy() { if (castContext != null) { castContext .getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession::class.java) } } }
public class MyService extends Service { private CastContext castContext; @Override protected void onCreate() { castContext = CastContext.getSharedInstance(this); castContext .getSessionManager() .addSessionManagerListener(sessionManagerListener, CastSession.class); } @Override protected void onDestroy() { if (castContext != null) { castContext .getSessionManager() .removeSessionManagerListener(sessionManagerListener, CastSession.class); } } }
今回のアップデートにより、ローカルからリモートへのキャストは、 バックグラウンドで動作しており、移行元の環境から Bluetooth デバイスをキャスト デバイスに接続する。
リモートからローカルへ
出力スイッチャーは、リモート再生から
またはローカルの Bluetooth デバイスに接続します。この設定を有効にするには、
setRemoteToLocalEnabled
CastOptions
でtrue
に報告しました。
現在の送信デバイスが複数の送信者を含む既存のセッションに参加していて、アプリが現在のメディアをローカルに転送できるかどうかを確認する必要がある場合は、SessionTransferCallback
の onTransferred
コールバックを使用して SessionState
を確認する必要があります。
setRemoteToLocalEnabled フラグを設定する
CastOptions.Builder
スマートフォンのスピーカーとローカルの Bluetooth デバイスを転送先として表示または非表示にする setRemoteToLocalEnabled
を提供します。
アクティブなキャスト セッションがある場合に、出力の切り替えダイアログに表示されます。
class CastOptionsProvider : OptionsProvider { fun getCastOptions(context: Context?): CastOptions { ... return Builder() ... .setRemoteToLocalEnabled(true) .build() } }
public class CastOptionsProvider implements OptionsProvider { @Override public CastOptions getCastOptions(Context context) { ... return new CastOptions.Builder() ... .setRemoteToLocalEnabled(true) .build() } }
ローカルでの再生を続行
リモートからローカルへの変換をサポートするアプリは、SessionTransferCallback
を登録する必要があります。
イベント発生時に通知を受け取れるようにして、メディアがアップロードされる
ローカルで転送して再生を続行できる権限があります。
CastContext#addSessionTransferCallback(SessionTransferCallback)
アプリがその SessionTransferCallback
を登録できるようにします。
また、onTransferred
と onTransferFailed
のコールバックをリッスンするのは
ローカル再生に転送します。
アプリが SessionTransferCallback
の登録を解除すると、次のようになります。
アプリは SessionTransferCallback
を受信しなくなります
SessionTransferCallback
は既存の SessionManagerListener
コールバックの拡張機能であり、onSessionEnded
がトリガーされた後にトリガーされます。データの
リモートからローカルへのコールバックは次のようになります。
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 対応に拡張する機能をサポートします。 ストリーミング拡張を使用するオーディオ アプリ用のスピーカー デバイス。
オーディオ アプリとは、レシーバー アプリで Google Cast for Audio に対応しているアプリのことです。 Google Cast SDK Developer の コンソール
スピーカーによるストリーミング拡張
出力スイッチャーを使用するオーディオ アプリでは、音声を拡大できます。 [ストリーミング] を使用したキャスト セッション中に複数の Cast 対応スピーカー デバイスに接続 拡張。
この機能は Cast プラットフォームでサポートされているため、これ以上の対応は必要ありません アプリがデフォルト UI を使用している場合、変更されます。カスタム UI を使用すると、 アプリがグループにキャストしていることを反映するように UI を更新します。
ストリーム拡張中に新しい拡張グループ名を取得するには、次の操作を行います。
登録して
Cast.Listener
使用
CastSession#addCastListener
。
次に呼び出します
CastSession#getCastDevice()
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); } }
リモート間のテスト
機能をテストするには:
- Cast 対応デバイスにコンテンツをキャストするには、通常のキャストを使用するか、 local-to-remote
- いずれかのエントリ ポイントを使用して出力スイッチャーを開きます。
- 別の Cast 対応デバイスをタップすると、オーディオ アプリのコンテンツが 動的グループを作成します
- Cast 対応デバイスをもう一度タップすると、デバイスがダイナミックから削除されます できます。