【Audio&Video】MediaRouteProvider概述(18)

Android媒体路由器框架允许制造商通过称为a的标准化接口在其设备上启用回放MediaRouteProvider。路由提供商定义了用于在接收设备上播放媒体的通用界面,从而可以从支持媒体路由的任何Android应用程序在设备上播放媒体。

本指南讨论如何为接收设备创建媒体路由提供程序,并使其可用于在Android上运行的其他媒体播放应用程序。为了使用这个API,你应该熟悉了重点班 MediaRouteProvider, MediaRouteProviderDescriptor和 RouteController。

概观


Android媒体路由器框架使媒体应用程序开发人员和媒体播放设备制造商能够通过通用API和通用用户界面进行连接。MediaRouter然后,实现接口的应用开发人员可以连接到框架,并将内容播放给参与媒体路由器框架的设备。媒体播放设备制造商可以通过发布MediaRouteProvider允许其他应用连接到并在接收设备上播放媒体的框架来参与该框架。图1说明了应用程序如何通过媒体路由器框架连接到接收设备。

【Audio&Video】MediaRouteProvider概述(18)
图1.媒体路由提供程序类提供从媒体应用程序到接收方设备的通信的概述。

当您为接收器设备构建媒体路由提供程序时,提供程序将用于以下目的:

描述和发布接收器设备的功能,以便其他应用可以发现它并使用其播放功能。
包装接收器设备的编程接口及其通信传输机制,以使设备与媒体路由器框架兼容。

路线提供者的分布

媒体路由提供程序是作为Android应用程序的一部分分发的。您的路由提供商可以通过扩展MediaRouteProviderService或包装 MediaRouteProvider您自己的服务实施并为媒体路由提供商声明一个意向过滤器,使其可用于其他应用 。这些步骤允许其他应用程序发现并利用您的媒体路线。

注意:包含媒体路由提供程序的应用程序也可以为路由提供程序包含 MediaRouter接口,但这不是必需的。

媒体路由器库

媒体路由器API在v7-mediarouter支持库中定义 。您必须将此库添加到您的应用开发项目中。有关将支持库添加到项目的更多信息,请参阅支持库设置。

警告:请务必使用android.support.v7.media 媒体路由器框架的实施。不要使用旧的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>

这个清单示例声明了一个包装实际媒体路由提供程序类的服务。Android媒体路由器框架提供了MediaRouteProviderService用作媒体路由提供者的服务包装的 类。以下示例代码演示了如何使用此包装类:

public class SampleMediaRouteProviderService extends MediaRouteProviderService {

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

指定路由功能


连接到媒体路由器框架的应用程序可以通过应用程序的清单声明来发现您的媒体路线,但他们也需要知道您提供的媒体路线的功能。媒体路线可以是不同的类型和不同的功能,其他应用程序需要能够发现这些细节以确定它们是否与您的路线兼容。

媒体路由器框架允许您通过IntentFilter对象,MediaRouteDescriptor对象和a 来定义和发布媒体路由的功能MediaRouteProviderDescriptor。本节介绍如何使用这些类发布其他应用的媒体路由的详细信息。

路线类别

作为媒体路径提供商的程序化描述的一部分,您必须指定您的提供商是否支持远程播放,辅助输出或两者。这些是由媒体路由器框架提供的路由类别:

CATEGORY_LIVE_AUDIO - 将音频输出到辅助输出设备,例如支持无线功能的音乐系统。
CATEGORY_LIVE_VIDEO - 将视频输出到辅助输出设备,例如无线显示设备。
CATEGORY_REMOTE_PLAYBACK- 在处理媒体检索,解码和播放的独立设备(如Chromecast设备)上播放视频或音频 。
为了将这些设置包含在媒体路径的描述中,可以将它们插入到一个IntentFilter对象中,然后添加到 MediaRouteDescriptor对象中:

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)定义支持远程视频播放的意图过滤器:

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,防止发送应用程序相互干扰。
以下代码示例演示如何构建支持基本媒体路径播放控件的意图过滤器:

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对象定义媒体路径的功能之后,您可以创建一个描述符对象以发布到Android媒体路由器框架。该描述符对象包含媒体路由功能的具体内容,以便其他应用程序可以确定如何与媒体路由进行交互。

以下示例代码演示了如何将以前创建的意图过滤器添加到 MediaRouteProviderDescriptor并设置介质路由器框架使用的描述符:

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);
}

有关可用的描述符设置的详细信息,请参阅参考文档MediaRouteDescriptor和MediaRouteProviderDescriptor。

控制路线


当应用程序连接到媒体路由提供程序时,提供程序会通过由其他应用程序发送到路由的媒体路由器框架接收回放命令。要处理这些请求,您必须提供一个MediaRouteProvider.RouteController类的实现,该类处理命令并处理与接收器设备的实际通信。

媒体路由器框架调用onCreateRouteController() 您的路由提供程序的方法来获取此类的实例,然后将请求路由到它。这些是MediaRouteProvider.RouteController班级的关键方法,您必须为媒体路线提供者实施这些方法:

onSelect() - 应用程序选择播放路线时调用。在媒体播放开始之前,您可以使用此方法执行任何可能需要的准备工作。
onControlRequest() - 将特定的播放命令发送到接收设备。
onSetVolume() - 向接收设备发送请求,将播放音量设置为特定值。
onUpdateVolume() - 向接收设备发送请求,将播放音量修改为指定的数量。
onUnselect() - 当应用程序取消选择路线时调用。
onRelease() - 在框架不再需要路由时调用,从而释放其资源。
所有播放控制请求(除音量更改外)都将指向该onControlRequest() 方法。你的这个方法的实现必须解析控制请求并适当地回应它们。以下是处理远程回放媒体路由命令的此方法的示例实现:

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, mSessionManager.toString());
            return success;
        }
        return false;
    }
    ...
}

了解MediaRouteProvider.RouteController该类旨在作为媒体播放设备API的包装器是很重要的。此类中方法的实现完全取决于接收设备提供的编程接口。

示例代码


Android的MediaRouter 示例演示如何创建一个自定义媒体路线提供商。

联系我

QQ:94297366
微信打赏:https://pan.baidu.com/s/1dSBXk3eFZu3mAMkw3xu9KQ

公众号推荐:

【Audio&Video】MediaRouteProvider概述(18)

猜你喜欢

转载自blog.51cto.com/4789781/2130806