앱 내에서 MediaRouter 프레임워크를 사용하려면 인스턴스를 가져와야 합니다.
MediaRouter
객체의 가장 유사한 값을 가져와서
라우팅 이벤트를 수신 대기하는 MediaRouter.Callback
객체
미디어 경로를 통해 전송된 콘텐츠는 경로의
연결된 MediaRouteProvider
(일부 특수한 경우 제외)
블루투스 출력 장치 등). 그림 1은
클래스가 사용됩니다.
![](https://developer.android.com/static/images/mediarouter/mediarouter-framework.png?authuser=9&hl=ko)
그림 1. 앱에서 사용하는 주요 미디어 라우터 클래스의 개요
참고: 앱에서 Google Cast 기기, Cast SDK를 사용하여 앱을 Cast 송신기로 빌드할 수 있습니다. 다음 안내를 따르세요. Cast 문서 MediaRouter 프레임워크를 직접 사용하는 대신
미디어 경로 버튼
Android 앱은 미디어 경로 버튼을 사용하여 미디어 라우팅을 제어해야 합니다. MediaRouter 프레임워크 사용자가 라우팅을 인식하고 사용하는 데 도움이 되는 버튼에 대한 표준 인터페이스를 제공합니다. (가능한 경우) 미디어 경로 버튼은 일반적으로 앱의 작업 모음에 표시됩니다.
![](https://developer.android.com/static/images/mediarouter/mediarouter-actionbar.png?authuser=9&hl=ko)
그림 2. 미디어 경로 버튼 확인할 수 있습니다
사용자가 미디어 경로 버튼을 누르면 사용 가능한 미디어 경로가 그림 3과 같이 목록에 표시됩니다.
![](https://developer.android.com/static/images/mediarouter/mediarouter-selector-ui.png?authuser=9&hl=ko)
그림 3. 미디어 경로 버튼을 누른 후 표시되는 사용 가능한 미디어 경로 목록
미디어 경로 버튼을 만들려면 다음 단계를 따르세요.
- AppCompatActivity 사용
- 미디어 경로 버튼 메뉴 항목 정의
- MediaRouteSelector 만들기
- 미디어 경로 버튼을 작업 모음에 추가
- 활동의 수명 주기에서 MediaRouter.Callback 메서드 만들기 및 관리
이 섹션에서는 처음 네 단계를 설명합니다. 다음 섹션에서는 콜백 메서드를 설명합니다.
AppCompatActivity 사용
활동에서 미디어 라우터 프레임워크를 사용할 때는
AppCompatActivity
에서 활동을 추가하고
androidx.appcompat.app
패키지 먼저
androidx.appcompat:appcompat
및 androidx.mediarouter:mediarouter
지원 라이브러리를 추가해야 합니다. 지원 라이브러리 추가에 대한 자세한 내용은
Android Jetpack 시작하기를 참고하세요.
주의: androidx
미디어 라우터 프레임워크입니다. 이전 android.media
패키지를 사용하지 마세요.
미디어 경로 버튼 메뉴 항목 정의
미디어 경로 버튼의 메뉴 항목을 정의하는 XML 파일을 만듭니다.
항목의 작업은 MediaRouteActionProvider
클래스여야 합니다
다음은 파일 예입니다.
// myMediaRouteButtonMenuItem.xml <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" > <item android:id="@+id/media_route_menu_item" android:title="@string/media_route_menu_title" app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider" app:showAsAction="always" /> </menu>
MediaRouteSelector 만들기
미디어 경로 버튼 메뉴에 표시되는 경로는 MediaRouteSelector
에서 판단합니다.
AppCompatActivity
의 활동 확장
활동이 생성될 때 MediaRouteSelector.Builder
를 호출하여 선택기를 빌드합니다.
onCreate() 메서드에서 삭제하세요.
를 사용할 수 있습니다. 선택기는 클래스 변수에 저장되고 허용되는 경로 유형이 지정됩니다.
MediaControlIntent
객체를 추가합니다.
Kotlin
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mSelector: MediaRouteSelector? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create a route selector for the type of routes your app supports. mSelector = MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build() } }
자바
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouteSelector mSelector; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Create a route selector for the type of routes your app supports. mSelector = new MediaRouteSelector.Builder() // These are the framework-supported intents .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) .build(); } }
대부분의 애플리케이션에서는
필요한 경로 유형은 CATEGORY_REMOTE_PLAYBACK
입니다. 이 경로 유형은 앱을 실행하는 기기를 리모컨으로 취급합니다.
연결된 수신 기기는 모든 콘텐츠 데이터 검색, 디코딩, 재생을 처리합니다.
다음과 같은 Google Cast를 지원하는 앱은 다음과 같습니다.
Chromecast, 직장
일부 제조업체는 '보조 출력'이라는 특수 라우팅 옵션을 지원합니다. 이 라우팅을 사용하면
미디어 앱이 동영상이나 음악을 검색하여 렌더링하여 선택된 원격 수신 기기의 화면이나 스피커로 직접 스트리밍합니다.
보조 출력을 사용하여 콘텐츠를 무선 지원 음악 시스템 또는 동영상 디스플레이로 전송합니다. 탐색 및
선택한 경우
CATEGORY_LIVE_AUDIO
또는
CATEGORY_LIVE_VIDEO
MediaRouteSelector로 컨트롤 카테고리를 추가합니다. 또한 자체 Presentation
대화상자를 만들고 처리해야 합니다.
미디어 경로 버튼을 작업 모음에 추가
미디어 경로 메뉴와 MediaRouteSelector가 정의되면 이제 미디어 경로 버튼을 활동에 추가할 수 있습니다.
각 활동의 onCreateOptionsMenu()
메서드를 재정의하여 옵션을 추가합니다.
선택합니다.
Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean { super.onCreateOptionsMenu(menu) // Inflate the menu and configure the media router action provider. menuInflater.inflate(R.menu.sample_media_router_menu, menu) // Attach the MediaRouteSelector to the menu item val mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item) val mediaRouteActionProvider = MenuItemCompat.getActionProvider(mediaRouteMenuItem) as MediaRouteActionProvider // Attach the MediaRouteSelector that you built in onCreate() selector?.also(mediaRouteActionProvider::setRouteSelector) // Return true to show the menu. return true }
자바
@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Inflate the menu and configure the media router action provider. getMenuInflater().inflate(R.menu.sample_media_router_menu, menu); // Attach the MediaRouteSelector to the menu item MenuItem mediaRouteMenuItem = menu.findItem(R.id.media_route_menu_item); MediaRouteActionProvider mediaRouteActionProvider = (MediaRouteActionProvider)MenuItemCompat.getActionProvider( mediaRouteMenuItem); // Attach the MediaRouteSelector that you built in onCreate() mediaRouteActionProvider.setRouteSelector(selector); // Return true to show the menu. return true; }
앱에 작업 모음을 구현하는 방법에 관한 자세한 내용은 작업 모음 참조하세요.
미디어 경로 버튼을 MediaRouteButton
로 추가할 수도 있습니다.
합니다. setRouteSelector()
메서드를 사용하여 MediaRouteSelector를 버튼에 연결해야 합니다. 자세한 내용은
Google Cast 디자인 체크리스트
을 참조하세요.
MediaRouter 콜백
동일한 기기에서 실행되는 모든 앱은 단일 MediaRouter
인스턴스와 해당 경로를 공유합니다.
(앱의 MediaRouteSelector로 앱별로 필터링됨) 각 활동은 MediaRouter와 통신합니다.
자체 MediaRouter.Callback
구현 사용
메서드를 참조하세요. MediaRouter는 사용자가 경로를 선택, 변경 또는 연결 해제할 때마다 콜백 메서드를 호출합니다.
콜백에는 다음과 같은 정보를 수신하기 위해 재정의할 수 있는 여러 메서드가 있습니다.
라우팅 이벤트입니다. 최소한 MediaRouter.Callback
클래스의 구현은 다음을 재정의해야 합니다.
onRouteSelected()
및
onRouteUnselected()
입니다.
MediaRouter는 공유 리소스이므로 앱에서 MediaRouter 콜백을 관리해야 함 다음과 같습니다.
- 활동이 만들어지면(
onCreate(Bundle)
)MediaRouter
포인터를 가져와 앱의 전체 기간 동안 유지하세요. - 활동이 표시되면 (
onStart()
) MediaRouter에 콜백을 연결하고 활동이 숨겨지면 분리합니다. (onStop()
).
다음 코드 샘플은
콜백 객체를 만들고 저장하는 방법,
MediaRouter
의 인스턴스와 콜백을 관리하는 방법을 가져올 수 있습니다.
onStart()
에서 콜백을 연결할 때 CALLBACK_FLAG_REQUEST_DISCOVERY
플래그를 사용해야 합니다.
이렇게 하면 MediaRouteSelector에서 미디어 경로 버튼의
사용 가능한 경로 목록입니다.
Kotlin
class MediaRouterPlaybackActivity : AppCompatActivity() { private var mediaRouter: MediaRouter? = null private var mSelector: MediaRouteSelector? = null // Variables to hold the currently selected route and its playback client private var mRoute: MediaRouter.RouteInfo? = null private var remotePlaybackClient: RemotePlaybackClient? = null // Define the Callback object and its methods, save the object in a class variable private val mediaRouterCallback = object : MediaRouter.Callback() { override fun onRouteSelected(router: MediaRouter, route: MediaRouter.RouteInfo) { Log.d(TAG, "onRouteSelected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Stop local playback (if necessary) // ... // Save the new route mRoute = route // Attach a new playback client remotePlaybackClient = RemotePlaybackClient(this@MediaRouterPlaybackActivity, mRoute) // Start remote playback (if necessary) // ... } } override fun onRouteUnselected( router: MediaRouter, route: MediaRouter.RouteInfo, reason: Int ) { Log.d(TAG, "onRouteUnselected: route=$route") if (route.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) { // Changed route: tear down previous client mRoute?.also { remotePlaybackClient?.release() remotePlaybackClient = null } // Save the new route mRoute = route when (reason) { MediaRouter.UNSELECT_REASON_ROUTE_CHANGED -> { // Resume local playback (if necessary) // ... } } } } } // Retain a pointer to the MediaRouter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Get the media router service. mediaRouter = MediaRouter.getInstance(this) ... } // Use this callback to run your MediaRouteSelector to generate the // list of available media routes override fun onStart() { mSelector?.also { selector -> mediaRouter?.addCallback(selector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY) } super.onStart() } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. override fun onStop() { mediaRouter?.removeCallback(mediaRouterCallback) super.onStop() } ... }
자바
public class MediaRouterPlaybackActivity extends AppCompatActivity { private MediaRouter mediaRouter; private MediaRouteSelector mSelector; // Variables to hold the currently selected route and its playback client private MediaRouter.RouteInfo mRoute; private RemotePlaybackClient remotePlaybackClient; // Define the Callback object and its methods, save the object in a class variable private final MediaRouter.Callback mediaRouterCallback = new MediaRouter.Callback() { @Override public void onRouteSelected(MediaRouter router, RouteInfo route) { Log.d(TAG, "onRouteSelected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Stop local playback (if necessary) // ... // Save the new route mRoute = route; // Attach a new playback client remotePlaybackClient = new RemotePlaybackClient(this, mRoute); // Start remote playback (if necessary) // ... } } @Override public void onRouteUnselected(MediaRouter router, RouteInfo route, int reason) { Log.d(TAG, "onRouteUnselected: route=" + route); if (route.supportsControlCategory( MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)){ // Changed route: tear down previous client if (mRoute != null && remotePlaybackClient != null) { remotePlaybackClient.release(); remotePlaybackClient = null; } // Save the new route mRoute = route; if (reason != MediaRouter.UNSELECT_REASON_ROUTE_CHANGED) { // Resume local playback (if necessary) // ... } } } } // Retain a pointer to the MediaRouter @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get the media router service. mediaRouter = MediaRouter.getInstance(this); ... } // Use this callback to run your MediaRouteSelector to generate the list of available media routes @Override public void onStart() { mediaRouter.addCallback(mSelector, mediaRouterCallback, MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); super.onStart(); } // Remove the selector on stop to tell the media router that it no longer // needs to discover routes for your app. @Override public void onStop() { mediaRouter.removeCallback(mediaRouterCallback); super.onStop(); } ... }
또한 미디어 라우터 프레임워크는
MediaRouteDiscoveryFragment
클래스:
액티비티의 콜백 삭제
참고: 음악 재생 앱을 작성 중이고 이 앱이 재생되도록 하려는 경우
음악이 백그라운드에서 재생되는 동안 재생되도록 하려면 Service
를 빌드해야 합니다.
서비스의 수명 주기 콜백에서 미디어 라우터 프레임워크를 호출할 수 있습니다.
원격 재생 경로 제어
원격 재생 경로를 선택하면 앱이 리모컨 역할을 합니다. 경로의 반대편 끝에 있는 기기
는 모든 콘텐츠 데이터 검색, 디코딩 및 재생 기능을 처리합니다. 앱 UI의 컨트롤은
RemotePlaybackClient
객체.
RemotePlaybackClient
클래스는 추가 메서드를 제공합니다.
몇 가지 옵션이 있습니다. 다음은 RemotePlaybackClient
클래스의 주요 재생 메서드입니다.
play()
— 특정 항목 재생Uri
로 지정된 미디어 파일입니다.pause()
— 현재 재생 중인 미디어 트랙입니다.resume()
- 계속 현재 트랙을 재생하도록 요청할 수 있습니다.seek()
— 특정 항목으로 이동 위치를 지정할 수 있습니다.release()
— 앱에서 원격 재생 기기로 연결되도록 해야 합니다.
이러한 메서드를 사용하여 있습니다. 이러한 메서드는 대부분 콜백 객체를 포함하여 재생 작업 또는 컨트롤 요청의 진행 상태를 나타냅니다.
RemotePlaybackClient
클래스는 다음 항목의 큐에 추가를 지원합니다.
미디어 대기열의 재생 및 관리를 위한 다중 미디어 항목
샘플 코드
Android BasicMediaRouter 및 MediaRouter 샘플에는 MediaRouter API의 사용 방법이 자세히 나와 있습니다.