Android 媒體路由器架構可讓製造商在裝置上啟用播放功能
經由名為 MediaRouteProvider
的標準化介面取得。
路徑提供者定義了在接收器裝置上播放媒體的通用介面
透過任何支援媒體的 Android 應用程式,在您的設備上播放媒體
路徑。
本指南將說明如何為接收器裝置建立媒體路線提供者,並為其建立
適用於在 Android 上執行的其他媒體播放應用程式。如要使用這個 API,您
應該熟悉這些主要類別
MediaRouteProvider
、
MediaRouteProviderDescriptor
和
RouteController
。
總覽
Android 媒體路由器架構可讓媒體應用程式開發人員和媒體播放裝置
,透過通用 API 和常見的使用者介面進行連結。符合以下條件的應用程式開發人員
實作 MediaRouter
介面,即可連線至
並向參與媒體路由器架構的裝置播放內容。媒體
播放裝置製造商可以發布 MediaRouteProvider
參與架構,讓其他應用程式可以
在接收器裝置上播放媒體。圖 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 範例顯示如何建立自訂媒體路線供應商。