MediaRouteProvider 개요

제조업체는 Android 미디어 라우터 프레임워크를 통해 기기에서 재생을 사용 설정할 수 있습니다. MediaRouteProvider라는 표준화된 인터페이스를 통해 구현됩니다. 경로 제공자는 수신 기기에서 미디어를 재생하기 위한 공통 인터페이스를 정의하여 미디어를 지원하는 모든 Android 애플리케이션을 통해 장비에서 미디어를 재생할 수 있음 경로.

이 가이드에서는 수신 기기의 미디어 경로 제공자를 만들고 이를 만드는 방법을 설명합니다. Android에서 실행되는 다른 미디어 재생 애플리케이션에서 사용할 수 있습니다. 이 API를 사용하려면 머신러닝 모델의 MediaRouteProvider님, MediaRouteProviderDescriptorRouteController:

개요

Android 미디어 라우터 프레임워크는 미디어 앱 개발자와 미디어 재생 기기를 지원합니다. 공통 API와 공통 사용자 인터페이스를 통해 연결할 수 있습니다. 앱을 개발하는 MediaRouter 인터페이스를 구현하여 콘텐츠를 재생할 수 있습니다. 미디어 재생 기기 제조업체는 다른 애플리케이션이 네트워크에 연결하여 보고하도록 허용하는 MediaRouteProvider를 게시하여 프레임워크에 참여할 수 있습니다. 수신 기기에서 미디어를 재생합니다. 그림 1은 앱이 수신 전화에 연결하는 방법을 보여줍니다. 미디어 라우터 프레임워크로 전달할 수 있습니다.

그림 1. 미디어 경로 제공자 클래스가 통신을 제공하는 방법에 관한 개요 수신 장치로 전달됩니다.

수신 기기의 미디어 경로 제공자를 빌드하면 제공자는 다음과 같은 목적으로 사용됩니다.

  • 다른 앱이 발견할 수 있도록 수신 기기의 기능을 설명하고 게시 재생 기능을 사용할 수 있습니다.
  • 수신 기기의 프로그래밍 인터페이스 및 통신 래핑 장치가 미디어 라우터 프레임워크와 호환되도록 합니다.

경로 제공자 배포

미디어 경로 제공자는 Android 앱의 일부로 배포됩니다. 경로 제공자는 다른 앱에서 사용할 수 있도록 확장함으로써 MediaRouteProviderService 또는 구현 래핑 자체 서비스로 MediaRouteProvider하고 인텐트 선언하기 미디어 경로 제공자의 필터입니다. 이러한 단계를 통해 다른 앱에서 선택합니다.

참고: 미디어 경로 제공자가 포함된 앱은 다음을 포함할 수도 있습니다. MediaRouter 인터페이스를 경로 제공자를 지정할 수 있지만 필수는 아닙니다.

MediaRouter 지원 라이브러리

미디어 라우터 API는 AndroidX MediaRouter 라이브러리 이 라이브러리를 앱 개발 프로젝트에 추가해야 합니다. 지원 라이브러리를 지원 라이브러리 설정을 참고하세요.

주의: AndroidX 미디어 라우터 프레임워크입니다. 이전 android.media 패키지를 사용하지 마세요.

제공자 서비스 만들기

미디어 라우터 프레임워크는 미디어 경로 제공자를 검색하고 연결할 수 있어야 합니다. 다른 애플리케이션이 해당 경로를 사용하도록 허용합니다. 이를 위해 미디어 라우터 프레임워크는 미디어 경로 제공자 인텐트 작업을 선언하는 앱을 찾습니다. 다른 앱에서 프레임워크가 제공자를 호출하고 연결할 수 있어야 합니다. 따라서 제공자는 Service에 캡슐화되어야 합니다.

다음 코드 예는 미디어 경로 제공자 서비스 및 미디어 라우터에서 검색하고 사용할 수 있도록 하는 매니페스트의 인텐트 필터 프레임워크:

<service android:name=".provider.SampleMediaRouteProviderService"
    android:label="@string/sample_media_route_provider_service"
    android:process=":mrp">
    <intent-filter>
        <action android:name="android.media.MediaRouteProviderService" />
    </intent-filter>
</service>

이 manifest 예는 실제 미디어 경로 제공자 클래스를 래핑하는 서비스를 선언합니다. Android 미디어 라우터 프레임워크는 서비스 래퍼로 사용할 MediaRouteProviderService 클래스 미디어 경로 제공자. 다음 코드 예는 이 래퍼를 사용하는 방법을 보여줍니다. 클래스:

Kotlin

class SampleMediaRouteProviderService : MediaRouteProviderService() {

    override fun onCreateMediaRouteProvider(): MediaRouteProvider {
        return SampleMediaRouteProvider(this)
    }
}

자바

public class SampleMediaRouteProviderService extends MediaRouteProviderService {

    @Override
    public MediaRouteProvider onCreateMediaRouteProvider() {
        return new SampleMediaRouteProvider(this);
    }
}

경로 기능 지정

미디어 라우터 프레임워크에 연결하는 앱은 앱의 매니페스트 선언을 지원하지만 개발자가 지정하는 미디어 경로의 기능도 알아야 합니다. 확인할 수 있습니다 미디어 경로는 다양한 유형일 수 있으며 다양한 기능과 기타 앱을 포함할 수 있습니다. 해당 정보가 경로와 호환되는지 확인하려면 이러한 세부정보를 탐색할 수 있어야 합니다.

미디어 라우터 프레임워크를 사용하면 미디어의 기능을 정의하고 게시할 수 있습니다. IntentFilter 객체, MediaRouteDescriptor 객체, MediaRouteProviderDescriptor를 통해 라우팅합니다. 이 섹션에서는 클래스를 사용하여 다른 앱에 대한 미디어 경로의 세부정보를 게시합니다.

경로 카테고리

미디어 경로 제공자의 프로그래매틱 설명의 일부로 제공자가 원격 재생, 보조 출력 또는 둘 다를 지원하는지를 알 수 있습니다. 다음은 경로입니다. 미디어 라우터 프레임워크에서 제공하는 카테고리입니다.

  • CATEGORY_LIVE_AUDIO — 무선 지원 음악 시스템과 같은 보조 출력 장치의 오디오 출력
  • CATEGORY_LIVE_VIDEO — 무선 디스플레이 장치와 같은 보조 출력 장치에 대한 비디오 출력입니다.
  • CATEGORY_REMOTE_PLAYBACK - 미디어를 처리하는 별도의 기기에서 동영상 또는 오디오 재생 검색, 디코딩 및 재생(예: Chromecast 기기.

미디어 경로의 설명에 이러한 설정을 포함하려면 IntentFilter 객체(나중에 MediaRouteDescriptor 객체:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            arrayListOf(this)
        }
    }
}

자바

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
}

CATEGORY_REMOTE_PLAYBACK 인텐트를 지정하는 경우 미디어 유형과 미디어의 유형도 정의해야 합니다. 미디어 경로 제공자가 재생 컨트롤을 지원합니다. 다음 섹션에서는 기기에서 이 설정을 지정할 수 있습니다.

미디어 유형 및 프로토콜

원격 재생 기기의 미디어 경로 제공자는 미디어 유형과 전송을 지정해야 합니다. 지원하는 프로토콜입니다 IntentFilter를 사용하여 이러한 설정을 지정합니다. 클래스와 addDataScheme()addDataType() 메서드를 호출합니다. 이 다음 코드 스니펫은 원격 동영상 지원을 위한 인텐트 필터를 정의하는 방법을 보여줍니다. http, https 및 RTSP (실시간 스트리밍 프로토콜)를 사용하여 동영상을 재생할 수 있습니다.

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {

        private fun IntentFilter.addDataTypeUnchecked(type: String) {
            try {
                addDataType(type)
            } catch (ex: IntentFilter.MalformedMimeTypeException) {
                throw RuntimeException(ex)
            }
        }

        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = IntentFilter().run {
            addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
            addAction(MediaControlIntent.ACTION_PLAY)
            addDataScheme("http")
            addDataScheme("https")
            addDataScheme("rtsp")
            addDataTypeUnchecked("video/*")
            arrayListOf(this)
        }
    }
    ...
}

자바

public final class SampleMediaRouteProvider extends MediaRouteProvider {

    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;

    static {
        IntentFilter videoPlayback = new IntentFilter();
        videoPlayback.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        videoPlayback.addAction(MediaControlIntent.ACTION_PLAY);
        videoPlayback.addDataScheme("http");
        videoPlayback.addDataScheme("https");
        videoPlayback.addDataScheme("rtsp");
        addDataTypeUnchecked(videoPlayback, "video/*");
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
    }
    ...

    private static void addDataTypeUnchecked(IntentFilter filter, String type) {
        try {
            filter.addDataType(type);
        } catch (MalformedMimeTypeException ex) {
            throw new RuntimeException(ex);
        }
    }
}

재생 컨트롤

원격 재생을 제공하는 미디어 경로 제공자는 미디어 컨트롤 유형을 지정해야 합니다. 살펴보겠습니다 다음은 미디어 경로에서 제공할 수 있는 일반적인 컨트롤 유형입니다.

  • 재생 컨트롤. 예: 재생, 일시중지, 되감기, 빨리 감기
  • 현재 재생목록 기능: 전송 앱에서 항목을 추가 및 삭제할 수 있음 수신 장치가 유지관리하는 재생목록으로부터 재생되도록 해야 합니다.
  • 세션 기능 - 전송 앱이 각 세션을 방해하지 않도록 방지 다른 하나는 수신 기기가 요청하는 앱에 세션 ID를 제공하도록 한 다음 각 후속 재생 컨트롤 요청에서 해당 ID를 호출합니다.

다음 코드 예는 다음을 지원하기 위한 인텐트 필터를 구성하는 방법을 보여줍니다. 기본 미디어 경로 재생 컨트롤:

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    companion object {
        ...
        private val CONTROL_FILTERS_BASIC: ArrayList<IntentFilter> = run {
            val videoPlayback: IntentFilter = ...
            ...
            val playControls = IntentFilter().apply {
                addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                addAction(MediaControlIntent.ACTION_SEEK)
                addAction(MediaControlIntent.ACTION_GET_STATUS)
                addAction(MediaControlIntent.ACTION_PAUSE)
                addAction(MediaControlIntent.ACTION_RESUME)
                addAction(MediaControlIntent.ACTION_STOP)
            }
            arrayListOf(videoPlayback, playControls)
        }
    }
    ...
}

자바

public final class SampleMediaRouteProvider extends MediaRouteProvider {
    private static final ArrayList<IntentFilter> CONTROL_FILTERS_BASIC;
    static {
        ...
        IntentFilter playControls = new IntentFilter();
        playControls.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
        playControls.addAction(MediaControlIntent.ACTION_SEEK);
        playControls.addAction(MediaControlIntent.ACTION_GET_STATUS);
        playControls.addAction(MediaControlIntent.ACTION_PAUSE);
        playControls.addAction(MediaControlIntent.ACTION_RESUME);
        playControls.addAction(MediaControlIntent.ACTION_STOP);
        CONTROL_FILTERS_BASIC = new ArrayList<IntentFilter>();
        CONTROL_FILTERS_BASIC.add(videoPlayback);
        CONTROL_FILTERS_BASIC.add(playControls);
    }
    ...
}

사용 가능한 재생 컨트롤 인텐트에 관한 자세한 내용은 MediaControlIntent 클래스.

MediaRouteProviderDescriptor

IntentFilter 객체를 사용하여 미디어 경로의 기능을 정의한 후에는 다음에 게시할 설명자 객체를 생성할 수 있습니다. 미디어 라우터 프레임워크입니다. 이 설명자 객체에는 미디어의 세부사항이 포함됩니다. 경로의 기능을 사용하여 다른 애플리케이션이 미디어와 상호 작용하는 방법을 결정할 수 있도록 합니다. 있습니다.

다음 코드 예는 이전에 만든 인텐트 필터를 MediaRouteProviderDescriptor하고 다음에서 사용할 설명어를 설정합니다. 미디어 라우터 프레임워크입니다.

Kotlin

class SampleMediaRouteProvider(context: Context) : MediaRouteProvider(context) {

    init {
        publishRoutes()
    }

    private fun publishRoutes() {
        val resources = context.resources
        val routeName: String = resources.getString(R.string.variable_volume_basic_route_name)
        val routeDescription: String = resources.getString(R.string.sample_route_description)
        // Create a route descriptor using previously created IntentFilters
        val routeDescriptor: MediaRouteDescriptor =
                MediaRouteDescriptor.Builder(VARIABLE_VOLUME_BASIC_ROUTE_ID, routeName)
                        .setDescription(routeDescription)
                        .addControlFilters(CONTROL_FILTERS_BASIC)
                        .setPlaybackStream(AudioManager.STREAM_MUSIC)
                        .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
                        .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
                        .setVolumeMax(VOLUME_MAX)
                        .setVolume(mVolume)
                        .build()
        // Add the route descriptor to the provider descriptor
        val providerDescriptor: MediaRouteProviderDescriptor =
                MediaRouteProviderDescriptor.Builder()
                        .addRoute(routeDescriptor)
                        .build()

        // Publish the descriptor to the framework
        descriptor = providerDescriptor
    }
    ...
}

자바

public SampleMediaRouteProvider(Context context) {
    super(context);
    publishRoutes();
}

private void publishRoutes() {
    Resources r = getContext().getResources();
    // Create a route descriptor using previously created IntentFilters
    MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder(
            VARIABLE_VOLUME_BASIC_ROUTE_ID,
            r.getString(R.string.variable_volume_basic_route_name))
            .setDescription(r.getString(R.string.sample_route_description))
            .addControlFilters(CONTROL_FILTERS_BASIC)
            .setPlaybackStream(AudioManager.STREAM_MUSIC)
            .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE)
            .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE)
            .setVolumeMax(VOLUME_MAX)
            .setVolume(mVolume)
            .build();
    // Add the route descriptor to the provider descriptor
    MediaRouteProviderDescriptor providerDescriptor =
            new MediaRouteProviderDescriptor.Builder()
            .addRoute(routeDescriptor)
            .build();

    // Publish the descriptor to the framework
    setDescriptor(providerDescriptor);
}

사용 가능한 설명어 설정에 관한 자세한 내용은 참조 문서를 확인하세요. MediaRouteDescriptorMediaRouteProviderDescriptor

경로 제어

애플리케이션이 미디어 경로 제공자에 연결되면 제공자가 재생을 수신합니다. 명령어에 대한 액세스를 제한할 수 있습니다. 이러한 문제를 요청을 처리하려면 명령어를 처리하는 MediaRouteProvider.RouteController 클래스의 구현을 제공해야 합니다. 수신 장치에 대한 실제 통신을 처리합니다.

미디어 라우터 프레임워크는 onCreateRouteController()를 호출합니다. 메서드를 사용하여 이 클래스의 인스턴스를 가져온 다음 요청을 이 인스턴스로 라우팅합니다. 다음은 MediaRouteProvider.RouteController 클래스의 주요 메서드이며 다음을 위해 구현해야 합니다. 미디어 경로 제공자:

  • onSelect() — 애플리케이션이 재생을 위해 경로를 선택할 때 호출됩니다. 이 메서드를 사용하여 미디어 재생이 시작되기 전에 필요할 수 있는 모든 준비 작업이 포함됩니다.
  • onControlRequest() - 특정 재생 명령어를 수신 기기로 전송합니다.
  • onSetVolume() - 수신 기기에 요청을 전송하여 재생 볼륨을 알 수 있습니다.
  • onUpdateVolume() - 수신 기기에 요청을 전송하여 재생을 수정합니다. 자동으로 조정합니다.
  • onUnselect() - 애플리케이션이 경로를 선택 해제할 때 호출됩니다.
  • onRelease() — 프레임워크에서 경로가 더 이상 필요하지 않을 때 호출되어 리소스를 배포합니다

볼륨 변경을 제외한 모든 재생 컨트롤 요청은 onControlRequest()로 전달됩니다. 메서드를 사용하여 축소하도록 요청합니다. 이 메서드의 구현은 제어 요청을 파싱하여 응답해야 합니다. 적절하게 조정할 수 있습니다 다음은 원격 재생 미디어 경로:

Kotlin

private class SampleRouteController : MediaRouteProvider.RouteController() {
    ...

    override fun onControlRequest(
            intent: Intent,
            callback: MediaRouter.ControlRequestCallback?
    ): Boolean {
        return if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            val action = intent.action
            when (action) {
                MediaControlIntent.ACTION_PLAY -> handlePlay(intent, callback)
                MediaControlIntent.ACTION_ENQUEUE -> handleEnqueue(intent, callback)
                MediaControlIntent.ACTION_REMOVE -> handleRemove(intent, callback)
                MediaControlIntent.ACTION_SEEK -> handleSeek(intent, callback)
                MediaControlIntent.ACTION_GET_STATUS -> handleGetStatus(intent, callback)
                MediaControlIntent.ACTION_PAUSE -> handlePause(intent, callback)
                MediaControlIntent.ACTION_RESUME -> handleResume(intent, callback)
                MediaControlIntent.ACTION_STOP -> handleStop(intent, callback)
                MediaControlIntent.ACTION_START_SESSION -> handleStartSession(intent, callback)
                MediaControlIntent.ACTION_GET_SESSION_STATUS ->
                    handleGetSessionStatus(intent, callback)
                MediaControlIntent.ACTION_END_SESSION -> handleEndSession(intent, callback)
                else -> false
            }.also {
                Log.d(TAG, sessionManager.toString())
            }
        } else {
            false
        }
    }
    ...
}

자바

private final class SampleRouteController extends
        MediaRouteProvider.RouteController {
    ...

    @Override
    public boolean onControlRequest(Intent intent, ControlRequestCallback callback) {

        String action = intent.getAction();

        if (intent.hasCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)) {
            boolean success = false;
            if (action.equals(MediaControlIntent.ACTION_PLAY)) {
                success = handlePlay(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_ENQUEUE)) {
                success = handleEnqueue(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_REMOVE)) {
                success = handleRemove(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_SEEK)) {
                success = handleSeek(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_STATUS)) {
                success = handleGetStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_PAUSE)) {
                success = handlePause(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_RESUME)) {
                success = handleResume(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_STOP)) {
                success = handleStop(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_START_SESSION)) {
                success = handleStartSession(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_GET_SESSION_STATUS)) {
                success = handleGetSessionStatus(intent, callback);
            } else if (action.equals(MediaControlIntent.ACTION_END_SESSION)) {
                success = handleEndSession(intent, callback);
            }

            Log.d(TAG, sessionManager.toString());
            return success;
        }
        return false;
    }
    ...
}

MediaRouteProvider.RouteController 클래스가 래퍼 역할을 하기 위한 것임을 알아야 합니다. 전송합니다. 이 클래스의 메서드 구현은 수신 기기에서 제공하는 프로그래매틱 인터페이스에 따라 완전히 달라집니다.

샘플 코드

MediaRouter 샘플은 커스텀 미디어 경로 제공자를 만드는 방법을 보여줍니다.