Android 媒體路由器架構可讓製造商在裝置上啟用播放功能
經由名為 MediaRouteProvider 的標準化介面取得。
路徑提供者定義了在接收器裝置上播放媒體的通用介面
透過任何支援媒體的 Android 應用程式,在您的設備上播放媒體
路徑。
本指南將說明如何為接收器裝置建立媒體路線提供者,並為其建立
適用於在 Android 上執行的其他媒體播放應用程式。如要使用這個 API,您
應該熟悉這些主要類別
MediaRouteProvider、
MediaRouteProviderDescriptor和
RouteController。
總覽
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>
這個資訊清單範例宣告的服務納入實際媒體路徑提供者類別。
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); } } }
播放控制項
提供遠端播放功能的媒體路由供應商必須指定媒體控制項類型 Kubernetes 環境以下是媒體路徑提供的一般控制項類型:
- 播放控制項,例如播放、暫停、倒轉和快轉。
- 排入佇列功能,可讓傳送應用程式新增及移除項目 從接收端裝置維護的播放清單中取樣。
- 工作階段功能:避免傳送應用程式乾擾各個工作階段 另一方式是透過接收端裝置為提出要求的應用程式提供工作階段 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); }
如要進一步瞭解可用的描述元設定,請參閱參考說明文件
MediaRouteDescriptor 和 MediaRouteProviderDescriptor。
控制路徑
應用程式連上媒體路由供應商後,供應商會接收播放內容
讓其他應用程式傳送到您的路線的媒體路由器架構。為了處理
要求,您必須提供用於處理指令的 MediaRouteProvider.RouteController 類別實作。
並處理與接收器裝置的實際通訊內容。
媒體路由器架構會呼叫 onCreateRouteController()
方法以取得這個類別的例項,然後轉送要求至該類別的例項。
以下是 MediaRouteProvider.RouteController 類別的主要方法,您必須對該類別實作這些方法
您的媒體轉送供應商:
onSelect()— 應用程式選擇播放路線時呼叫。您可以使用這個方法 開始播放媒體前可能需要的準備工作。onControlRequest():將特定播放指令傳送至接收裝置。onSetVolume():向接收裝置傳送要求,將播放音量設為 特定值。onUpdateVolume():將要求傳送至接收裝置,以便修改播放內容 指定磁碟區的用量onUnselect():應用程式取消選取路徑時呼叫。onRelease()— 架構不再需要路線時呼叫,以釋放路線 再複習一下,機構節點 是所有 Google Cloud Platform 資源的根節點
所有播放控制項要求 (音量變更除外) 都會導向「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 } } ... }
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 類別的用途是做為包裝函式
將 API 新增至媒體播放設備此類別中方法的實作方式為
完全依賴接收裝置提供的程式輔助介面。
程式碼範例
MediaRouter 範例顯示如何建立自訂媒體路線供應商。