MediaRouteProvider の概要

Android メディア ルーター フレームワークにより、メーカーは自社のデバイスで再生を有効にできます。 MediaRouteProviderという標準化されたインターフェースを通じて Google Cloud リソースにアクセスできます ルート プロバイダは、受信デバイスでメディアを再生するための共通インターフェースを定義し、 メディアに対応した Android アプリから、機器でメディアを再生できる routes:

このガイドでは、受信デバイスのメディアルート プロバイダを作成し、 Android で実行される他のメディア再生アプリでも利用できます。この API を使用するには、 主なクラスについて学び、 MediaRouteProvider MediaRouteProviderDescriptorRouteController

概要

Android メディア ルーター フレームワーク: メディアアプリのデベロッパーとメディア再生デバイス 共通の API とユーザー インターフェースを介して接続できます。アプリ デベロッパー MediaRouter インターフェースを実装すれば、 メディア ルーター フレームワークに参加しているデバイスでコンテンツを再生します。メディア 再生デバイス メーカーは、他のアプリが接続して接続できるようにする MediaRouteProvider を公開することで、このフレームワークに参加できます。 受信デバイスでメディアを再生する図 1 は、アプリが受信側 デバイスに直接接続できます

図 1. メディアルート プロバイダのクラスが通信を提供する方法の概要 受信側のデバイスへの 送信を許可するかどうかを決定します

受信デバイス用のメディアルート プロバイダを構築すると、そのプロバイダは 次のような目的があります。

  • 受信デバイスの機能を記述して公開し、他のアプリが検出できるようにする その再生機能を使用します。
  • 受信デバイスのプログラミング インターフェースとその通信をラップする トランスポート メカニズムを使用して、デバイスとメディア ルーター フレームワークとの互換性を確保します。

ルート プロバイダの配布

メディアルート プロバイダは、Android アプリの一部として配布されます。経路プロバイダは 拡張することで、他のアプリでも利用 MediaRouteProviderService を使用するか、 MediaRouteProvider を独自のサービスに置き換え、インテントを宣言する フィルタを設定します。この手順により、他のアプリが 選択します。

注: メディアルート プロバイダを含むアプリには、 MediaRouter インターフェースから 必須ではありませんが、使用する必要はありません。

MediaRouter サポート ライブラリ

メディア ルーター API は、 AndroidX MediaRouter ライブラリ このライブラリをアプリ開発プロジェクトに追加する必要があります。 サポート ライブラリを Support Library のセットアップをご覧ください。

注意: 必ず 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>

このマニフェストの例では、実際のメディアルート プロバイダ クラスをラップするサービスを宣言しています。 Android メディア ルーター フレームワークは、 サービス ラッパーとして使用する MediaRouteProviderService クラス 使用されます次のサンプルコードは、このラッパーの使用方法を示しています。 クラス:

Kotlin

class SampleMediaRouteProviderService : MediaRouteProviderService() {

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

Java

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

Java

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

Java

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

Java

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 を使用して、次のタスクで使用する記述子を設定します。 メディア ルーター フレームワーク:

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
    }
    ...
}

Java

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() に転送されます。 メソッドを呼び出します。このメソッドの実装では、コントロール リクエストを解析し、それに応答する必要があります。 適切に分類しますこのメソッドの実装例は、API 呼び出しでコマンドを処理する リモート再生メディアルート:

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
        }
    }
    ...
}

Java

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 サンプルは、カスタム メディアルート プロバイダを作成する方法を示しています。