您必須取得執行個體,才能在應用程式中使用 MediaRouter 架構
MediaRouter
物件的結構,並附加
用於監聽轉送事件的 MediaRouter.Callback
物件。
透過媒體路徑傳送的內容會通過路徑的
相關聯的 MediaRouteProvider
(除了少數特殊情況外)
例如藍牙輸出裝置)。圖 1 概略說明瞭
用來在裝置之間轉送內容的類別。
注意:要讓應用程式提供支援服務 Google Cast 裝置、 您應使用 Cast SDK 並將應用程式建構為 Cast 發送端請依照 投放說明文件 而不是直接使用 MediaRouter 架構
媒體路徑按鈕
Android 應用程式應使用媒體路徑按鈕控制媒體轉送功能。MediaRouter 架構 提供標準按鈕介面,方便使用者辨識及使用 並設為「優先」媒體路徑按鈕通常位於 應用程式的動作列,如圖 2 所示。
使用者按下媒體路線按鈕時,可用的媒體路線就會顯示在清單中,如圖 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() } }
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,工作。
部分製造商支援名為「次要輸出」的特殊轉送選項。有了這個轉送方式
媒體應用程式會擷取、算繪及串流播放影片或音樂,並直接串流至所選遠端接收器裝置的螢幕和/或喇叭。
使用次要輸出將內容傳送到支援無線功能的音樂系統或視訊顯示器。如要探索
挑選所需裝置,您需要將
CATEGORY_LIVE_AUDIO
或
CATEGORY_LIVE_VIDEO
控制 MediaRouteSelector。此外,您也需要建立和處理自己的 Presentation
對話方塊。
在動作列中新增媒體路徑按鈕
定義媒體路徑選單和 MediaRouteSelector 後,您現在可將媒體路徑按鈕新增至活動。
為每個活動覆寫 onCreateOptionsMenu()
方法,即可新增選項
或前往 Google 試算表選單
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
才能播放
並從服務的生命週期回呼中呼叫媒體路由器架構。
控制遠端播放路徑
選取遠端播放路徑時,您的應用程式會充當遙控器。路線另一端的裝置
會處理所有內容資料擷取、解碼和播放功能。應用程式使用者介面中的控制項會使用
RemotePlaybackClient
物件。
RemotePlaybackClient
類別提供其他方法
管理內容播放方式以下是一些 RemotePlaybackClient
類別的主要播放方法:
play()
- 播放特定媒體Uri
所指定的媒體檔案。pause()
- 暫停 目前正在播放媒體曲目。resume()
- 繼續 暫停播放目前的曲目。seek()
:移至特定 位於目前播放軌中的位置。release()
- 卸除 連結應用程式與遠端播放裝置。
你可以使用上述方法,將動作附加至你在 應用程式。這些方法大多都允許納入回呼物件,方便您監控 播放工作或控制要求的進度。
RemotePlaybackClient
類別也支援將
多個媒體項目用於播放及管理媒體佇列。
程式碼範例
Android BasicMediaRouter 和 MediaRouter 範例,進一步示範如何使用 MediaRouter API。