MediaRouter の概要

アプリで MediaRouter フレームワークを使用するには、インスタンスを取得する必要があります。 MediaRouter オブジェクトの ルーティング イベントをリッスンする MediaRouter.Callback オブジェクト。 メディアルートを介して送信されたコンテンツは、ルートの 関連付けられた MediaRouteProvider(ただし、 Bluetooth 出力デバイスなどです。図 1 は、 デバイス間でのコンテンツのルーティングに使用されるクラス。

図 1. アプリで使用される主なメディア ルーター クラスの概要。

注: アプリで Google Cast デバイス、 Cast SDK キャスト センダーとしてアプリをビルドします。 Cast のドキュメント 直接使用するのではなく

メディアルート ボタン

Android アプリでは、メディアルート ボタンを使用してメディアのルーティングを制御します。MediaRouter フレームワーク ユーザーがルーティングを認識して使用する際に役立つ、ボタンの標準インターフェースを提供する 提供しますメディアルート ボタンは通常、 アプリのアクションバーに追加できます(図 2 を参照)。

図 2. メディアルート ボタン クリックします。

ユーザーがメディアルート ボタンを選択すると、利用可能なメディアルートのリストが表示されます(図 3 参照)。

図 3. メディアルート ボタンを押すと表示される、利用可能なメディアルートのリスト。

メディアルート ボタンの作成手順は次のとおりです。

  1. AppCompatActivity を使用する
  2. メディアルート ボタンのメニュー項目を定義する
  3. MediaRouteSelector を作成する
  4. メディアルート ボタンをアクションバーに追加する
  5. アクティビティのライフサイクルで MediaRouter.Callback メソッドを作成し管理する

このセクションでは、最初の 4 つの手順について説明します。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()
    }
}

Java

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

メーカーによっては、「セカンダリ出力」と呼ばれる特別なルーティング オプションをサポートしています。このルーティングでは メディアアプリは、動画や音楽を、選択したリモート受信デバイスの画面やスピーカーに直接取得、レンダリング、ストリーミングします。 セカンダリ出力を使用すれば、ワイヤレス対応の音楽システムやビデオ ディスプレイにコンテンツを送信できます。検出と検出を有効にするには、 選択するには、該当するデバイス ID を 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
}

Java

@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 へのポインタを取得し、アプリの有効期間中はそのポインタを保持する。
  • アクティビティが表示されるようになったときにコールバックを MediaRouter にアタッチし(onStart())、非表示のときにデタッチする (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()
    }
    ...
}

Java

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 を作成する必要があります。 Service のライフサイクル コールバックからメディア ルーター フレームワークを呼び出します。

リモート再生ルートの制御

リモート再生ルートを選択した場合は、アプリはリモコンとして機能します。経路の反対側にあるデバイス は、コンテンツ データの取得、デコード、再生のすべての機能を処理します。アプリの UI のコントロールは、 RemotePlaybackClient オブジェクト。

RemotePlaybackClient クラスには、追加のメソッドが用意されています。 コンテンツ再生の管理に使用できます。以下に、RemotePlaybackClient クラスの主要な再生メソッドをいくつか示します。

  • play() - 特定の曲を再生する Uri で指定されたメディア ファイル。
  • pause() - 一時停止します。 再生中のメディア トラック。
  • resume() - 続行 一時停止コマンドの後、現在のトラックを再生する
  • seek() - 特定の場所に移動する 現在のトラックの位置を示します。
  • release() - 破棄します。 接続する必要があります。

以下のメソッドを使用して、 。これらのメソッドのほとんどは、コールバック オブジェクトを含めることができるので、 再生タスクまたはコントロール リクエストの進行状況。

RemotePlaybackClient クラスは、 メディアキューの再生と管理のための複数のメディア アイテム。

サンプルコード

Android BasicMediaRouter および MediaRouter サンプルでは、MediaRouter API の使用方法をさらに詳しく説明しています。