實施無線電

本頁介紹如何在硬體和軟體層級實現無線電。

系統組成

廣播無線電堆疊包括以下組件。

廣播電台架構
圖 1.廣播電台架構

無線電參考應用程式

無線控制的實作方法請參考無線控制的實作

範例 Java 無線電應用程式 ( packages/apps/Car/Radio ) 用作參考實作。當應用程式服務啟動時,它會請求無線電管理器開啟無線電調諧器。然後,應用程式可以向廣播調諧器發送請求,例如調諧到特定廣播電台、頻率或尋找下一個可用廣播電台。該應用程式從廣播中的廣播管理器和廣播調諧器接收更新,例如當前節目資訊、廣播節目清單、配置和供應商定義的參數。參考收音機應用程式僅支援 AM 和 FM 收音機。 OEM 可以根據需要修改或取代 Radio 應用程式。

電台經理

當應用程式請求無線電管理器開啟調諧器時,無線電管理器( frameworks/base/core/java/android/hardware/radio/RadioManager.java )請求廣播無線電服務開啟調諧器會話,然後將會話包裝在無線電調諧器 ( frameworks/base/core/java/android/hardware/radio/RadioTuner.java ),返回應用程式。廣播調諧器定義了可以從廣播應用程式呼叫並向廣播廣播服務發送請求的 API(例如調諧、步進和取消)。無線電調諧器中定義的回調方法 ( RadioTuner.Callback ) 將有關廣播無線電 HAL 的更新從廣播無線電服務發送到應用程序,例如當前節目資訊、節目列表和供應商定義的參數。

廣播電台服務

廣播廣播服務 ( frameworks/base/services/core/java/com/android/server/broadcastradio ) 是廣播廣播 HAL 的客戶服務。廣播無線電服務透過廣播無線電 HAL 協調多個無線電管理器。廣播廣播服務支援HAL 介面定義語言 (HIDL)Android 介面定義語言 (AIDL)廣播廣播 HAL。當任何 AIDL HAL 服務存在時,廣播廣播服務會連結到 AIDL HAL;否則,服務將連結到 HIDL HAL。廣播無線電服務為每個可用的 HAL 實例(例如 AM、FM 和 DAB)建立無線電模組。

每個無線電管理器都可以請求廣播無線電服務根據無線電類型在相應的無線電模組上建立調諧器會話。每個調諧器會話都可以呼叫tune、step和cancel(在HAL介面中定義)等方法來對對應的廣播無線電HAL實例執行操作。當一個調諧器會話收到來自HAL 實例的有關HAL 更新的回調(例如當前節目資訊、節目列表、配置標誌和供應商參數)時,有關更新的回調將發送到連結到同一無線電模組的所有無線電調諧器。

廣播電台 HAL

若要詳細了解廣播廣播的 HIDL 和 AIDL 介面以及兩者之間的差異,請參閱廣播廣播 HAL 介面

廣播無線電硬體抽象層

以下各節介紹如何使用硬體抽象層 (HAL) 來實現廣播無線電。

廣播電台 HAL 接口

廣播無線電 HAL 提供硬體層級的資料結構和介面來實現廣播無線電,例如 AM/FM 和 DAB 無線電。

HIDL 2.0 和 AIDL 介面

廣播無線電 HAL 使用以下部分中所述的介面。

公告監聽器

IAnnouncementListener是公告監聽器的回調接口,可以在廣播電台 HAL 上註冊來接收公告。此介面有以下方法:

I公告監聽器
描述:每當公告清單發生變更時呼叫。
HIDL 2.0 oneway onListUpdated(vec<Announcement> announcements)
人工智慧DL oneway void onListUpdated(in Announcement[] announcements)
關閉手柄

ICloseHandle是通用關閉句柄,用於刪除不需要活動介面的回呼。

I關閉句柄
描述:關閉手柄。
HIDL 2.0 close()
人工智慧DL void close()

回呼介面

ITunerCallback是廣播無線電 HAL 呼叫的回調接口,用於向 HAL 用戶端服務發送更新。

ITuner回呼
說明:當調整操作(調整、尋找(在 AIDL 中)或掃描(在 HIDL 中)和步驟成功)非同步失敗時由 HAL 呼叫。
HIDL 2.0 oneway onCurrentProgramInfoChanged(ProgramInfo info)
人工智慧DL void onCurrentProgramInfoChanged(in ProgramInfo info)
描述:當調諧、查找(在 AIDL 中)或掃描(在 HIDL 中)或步驟成功時調用。
HIDL 2.0 oneway onTuneFailed(Result result, ProgramSelector selector)
人工智慧DL void onTuneFailed(in Result result, in ProgramSelector selector)
描述:當調諧、查找(在 AIDL 中)或掃描(在 HIDL 中)或步驟成功時調用。
HIDL 2.0 oneway onCurrentProgramInfoChanged(ProgramInfo info)
人工智慧DL void onCurrentProgramInfoChanged(in ProgramInfo info)
說明:節目清單更新時調用;每個區塊的大小應限制為 500kiB。
HIDL 2.0 oneway onProgramListUpdated(ProgramListChunk chunk)
人工智慧DL oneway onProgramListUpdated(ProgramListChunk chunk)
描述:當天線連接或斷開時呼叫。
HIDL 2.0 oneway onAntennaStateChange(bool connected)
人工智慧DL void onCurrentProgramInfoChanged(in ProgramInfo info)
描述:當供應商特定的參數值在 HAL 中內部更新時呼叫(不應在 HAL 用戶端呼叫setParameters後呼叫)。
HIDL 2.0 oneway onParametersUpdated(vec<VendorKeyValue> parameters)
人工智慧DL void onParametersUpdated(in VendorKeyValue[] parameters)
描述: AIDL 中的新增功能。當 HAL 內部更新配置標誌時呼叫(不應在 HAL 用戶端呼叫setConfigFlag後呼叫)。
HIDL 2.0不適用。
人工智慧DL void onConfigFlagUpdated(in ConfigFlag flag, in boolean value)

主要廣播電台 HAL 接口

IBroadcastRadio是廣播無線電 HAL 的主要介面。在 HIDL 2.0 HAL 中,使用ITunerSession介面向 Tuner 呼叫操作。但是,一次最多有一個調諧器處於活動狀態(前提是每個廣播無線電 HAL 實例只有一個調諧器晶片)。 ITunerSession已從 AIDL 介面中刪除,其介面已移至IBroadcastRadio

廣播電台
描述:取得模組及其功能的描述。
HIDL 2.0 getProperties() generates (Properties properties)
人工智慧DL Properties getProperties()
說明:取得目前或可能的 AM/FM 區域配置。
HIDL 2.0 getAmFmRegionConfig(bool full) generates (Result result, AmFmRegionConfig config)
人工智慧DL AmFmRegionConfig getAmFmRegionConfig(bool full)
描述:取得目前 DAB 區域配置。
HIDL 2.0 getDabRegionConfig() generates (Result result, vec<DabTableEntry> config)
人工智慧DL DabTableEntry[] getDabRegionConfig()
描述:從無線電模組快取中獲取影像。在 AIDL 中,由於 Binder 事務緩衝區的硬限制,影像大小必須小於 1MB。
HIDL 2.0 getImage(uint32_t id) generates (vec<uint8_t> image)
人工智慧DL byte[] getImage(in int id)
說明:註冊公告監聽器。
HIDL 2.0 registerAnnouncementListener(vec<AnnouncementType> enabled,IAnnouncementListener listener) generates (Result result, ICloseHandle closeHandle)
人工智慧DL ICloseHandle registerAnnouncementListener(in IAnnouncementListener listener, in AnnouncementType[] enabled)
描述:
  • HIDL HAL:開啟新的調諧器會話時,必須終止舊會話。
  • AIDL HAL:由於沒有可用的 Tuner 會話,因此只需要設定 Tuner 回呼。如果存在,則應取消設定舊回呼。
HIDL 2.0 openSession(ITunerCallback callback)產生(Result result, ITunerSession session)
人工智慧DL void setTunerCallback(in ITunerCallback callback)
描述:
  • HIDL HAL:關閉調諧器會話不得失敗,且只能發出一次。
  • AIDL HAL:沒有調諧器,只需取消設定調諧器回呼。
HIDL 2.0 close()
人工智慧DL unsetTunerCallback()
說明:調至指定的節目。
HIDL 2.0 tune(ProgramSelector program) generates (Result result)
人工智慧DL void tune(in ProgramSelector program)
描述:尋找下一個有效的廣播節目。為了避免 AIDL 中的混淆, scan被重新命名為seek
HIDL 2.0 scan(bool directionUp, bool skipSubChannel) generates (Result result)
人工智慧DL void seek(in boolean directionUp, in boolean skipSubChannel)
說明:進入相鄰頻道,該頻道不得被任何節目佔用。
HIDL 2.0 step(bool directionUp) generates (Result result)
人工智慧DL void step(in boolean directionUp)
說明:取消掛起的調諧、掃描(在 HIDL 中)或尋找(在 AIDL 中)或步驟操作。
HIDL 2.0 cancel()
人工智慧DL void cancel()
描述:將篩選器套用至程式列表,並開始透過onProgramListUpdated回呼發送程式列表更新。
HIDL 2.0 startProgramListUpdates(ProgramFilter filter) generates (Result result)
人工智慧DL void startProgramListUpdates(in ProgramFilter filter)
描述:停止發送節目清單更新。
HIDL 2.0 stopProgramListUpdates()
人工智慧DL void stopProgramListUpdates()
描述:取得給定配置標誌的目前設定。
HIDL 2.0 isConfigFlagSet(ConfigFlag flag) generates (Result result, bool value)
人工智慧DL boolean isConfigFlagSet(in ConfigFlag flag)
描述:設定給定的配置標誌。
HIDL 2.0 setConfigFlag(ConfigFlag flag, bool value) generates (Result result)
人工智慧DL void setConfigFlag(in ConfigFlag flag, boolean value)
描述:設定供應商特定的參數值。
HIDL 2.0 setParameters(vec<VendorKeyValue> parameters)

生成,

(vec<VendorKeyValue> results)
人工智慧DL VendorKeyValue[] setParameters(in VendorKeyValue[] parameters)
描述:檢索供應商特定的參數值。
HIDL 2.0 getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters)
人工智慧DL VendorKeyValue[] getParameters(in String[] keys)

介面說明

異步行為

由於每個調優操作(例如,調優、掃描(在 HIDL 中)或尋找(在 AIDL 中)和步驟)可能很耗時,且執行緒不應該長時間阻塞,因此該操作應該調度耗時的操作稍後發生並快速返回狀態或結果。具體來說,每個操作應該:

  • 取消所有掛起的調整操作。
  • 根據方法輸入和調諧器的狀態檢查是否可以處理該操作。
  • 安排調優任務,然後立即傳回Result (在 HIDL 中)或status (在 AIDL 中)。如果ResultstatusOK ,則當調優任務失敗(例如,由於逾時)或完成時,必須呼叫調優器回呼tuneFailedcurrentProgramInfoChanged

類似地, startProgramListUpdates也安排稍後執行更新程式清單的耗時任務並快速返回狀態或結果。此方法首先取消掛起的更新要求,然後調度更新任務並快速返回結果。

比賽條件

由於調優操作(例如,調優、掃描(在 HIDL 中)或查找(在 AIDL 中)和步進)的異步行為,取消操作和調優操作之間存在競爭條件。如果在 HAL 完成調整操作之後且回調完成之前呼叫cancel ,則可以忽略取消,並且回呼應該完成並由 HAL 用戶端接收。

同樣,如果 HAL 完成程式清單更新之後且onCurrentProgramInfoChanged回呼完成之前呼叫stopProgramListUpdates ,則可以忽略stopProgramListUpdates並且回呼應該完成。

資料大小限制

由於綁定器事務緩衝區存在硬性限制,因此 AIDL HAL 中明確了某些傳遞可能較大尺寸資料的介面方法的資料限制。

  • getImage要求傳回的映像小於 1 MB。
  • onProgramListUpdate要求每個chunk小於 500kiB。較大的程式清單必須由 HAL 實作分割成多個區塊並透過多個回呼發送。

AIDL HAL 資料結構的變化

除了介面的變更之外,這些變更還應用於廣播無線電 AIDL HAL 中定義的資料結構,它利用了 AIDL。

  • AIDL 中刪除了Constant枚舉,並在IBroadcastRadio中定義為 const int 。同時, ANTENNA_DISCONNECTED_TIMEOUT_MS被重新命名為ANTENNA_STATE_CHANGE_TIMEOUT_MS 。新增了新的 const int TUNER_TIMEOUT_MS 。所有調諧、搜尋和步進操作都必須在這段時間內完成。
  • Enum RDSDeemphasis在 AIDL 中被刪除,並在AmFmRegionConfig中定義為 const int 。相應地, ProgramInfo中的fmDeemphasisfmRds都被宣告為int,也就是各自標誌位元的位元計算結果。同時, D50D75分別重新命名為DEEMPHASIS_D50DEEMPHASIS_D75
  • 枚舉ProgramInfoFlags在 AIDL 中被刪除,並在ProgramInfo中定義為 const int,並添加了前綴FLAG_ 。相應地, ProgramInfo中的infoFlags被宣告為int,即flags的位元計算結果。 TUNED也被重新命名為FLAG_TUNABLE ,以更好地描述電台可以調諧到的定義。
  • AmFmBandRange中, scanSpacing被重新命名為seekSpacing ,因為在AIDL 中scan被重新命名為seek
  • 由於 AIDL 中引入了union的概念,因此不再使用 HIDL HAL 中定義的MetadataKeyMetadata 。 AIDL 聯合元Metadata在 AIDL HAL 中定義。之前MetadataKey中的每個枚舉值現在是Metadata中的一個字段,其類型為 string 或 int,具體取決於它們的定義。

無線電控制實施

無線電控制實作基於MediaSessionMediaBrowse ,使媒體和語音助理應用程式能夠控制無線電。有關更多信息,請參閱developer.android.com 上的構建汽車媒體應用程式

媒體瀏覽樹實作在packages/apps/Car/libs中的car-broadcastradio-support 庫中提供。該程式庫還包含用於與 URI 相互轉換的 ProgramSelector 擴充。建議無線電實作使用此程式庫來建立關聯的瀏覽樹。

媒體來源切換器

為了提供廣播和媒體中顯示的其他應用程式之間的無縫轉換,car-media-common 庫包含應整合到廣播應用程式中的類別。 MediaAppSelectorWidget可以包含在廣播應用程式的 XML 中(參考媒體和廣播應用程式中使用的圖示和下拉式選單):

<com.android.car.media.common.MediaAppSelectorWidget
     android:id="@+id/app_switch_container"
     android:layout_width="@dimen/app_switch_widget_width"
     android:layout_height="wrap_content"
     android:background="@drawable/app_item_background"
     android:gravity="center" />

此小工具啟動AppSelectionFragment ,它顯示可以切換到的媒體來源清單。如果需要提供的 UI 以外的 UI,您可以建立自訂小工具以在應顯示切換器時啟動AppSelectionFragment

AppSelectionFragment newFragment = AppSelectionFragment.create(widget,
            packageName, fullScreen);
    newFragment.show(mActivity.getSupportFragmentManager(), null);

參考無線電應用程式實作中提供了範例實現,位於packages/apps/Car/Radio中。

詳細控制規範

MediaSession (透過MediaSession.Callback )介面為目前播放的廣播節目提供控制機制:

  • onPlayonStop 。 (取消)無線電播放靜音。
  • onPause 。時移暫停(如果支援)。
  • onPlayFromMediaId 。播放頂級資料夾中的任何內容。例如,“播放 FM”或“播放廣播”。
  • onPlayFromUri 。播放特定頻率。例如,「播放 88.5 FM」。
  • onSkipToNextonSkipToPrevious 。調至下一個或上一個電台。
  • onSetRating 。在收藏夾中新增或刪除。

MediaBrowser 在三種類型的頂級目錄上公開可調MediaItem

  • 可選節目(站)。雙調諧器無線電通常使用此模式來指示使用者位置處所有可用的可調諧無線電台。
  • 收藏夾。廣播節目已添加至收藏夾列表,但某些節目可能無法使用(超出接收範圍)。
  • 頻段頻道。目前區域中所有物理上可能的頻道(87.9、88.1、88.3、88.5、88.7、88.9、89.1 等)。每個樂隊都有一個單獨的頂級目錄。
MediaBrowserService 樹狀結構
圖 2. MediaBrowserService 樹狀結構

每個資料夾(AM/FM/Programs)中的每個元素都是具有 URI 的 MediaItem,可與 MediaSession 一起使用進行調整。每個頂級資料夾(AM/FM/Programs)都是一個具有 mediaId 的 MediaItem,可與 MediaSession 一起使用來觸發播放,並由 OEM 自行決定。例如,「播放 FM」、「播放 AM」和「播放廣播」都是使用 mediaId 發送到 OEM 廣播應用的非特定廣播查詢。由廣播應用程式根據通用請求和 mediaId 確定要播放的內容。

媒體會議

由於沒有暫停廣播串流的概念,因此播放、暫停和停止操作並不總是適用於廣播。對於廣播,「停止」操作與使串流靜音相關聯,而「播放」操作與刪除靜音相關聯。

某些廣播調諧器(或應用程式)提供透過快取內容然後稍後播放來模擬廣播串流暫停的功能。在這種情況下,請使用onPause

從 mediaId 和 URI 操作播放的目的是調諧到從 MediaBrowser 介面取得的電台。 mediaId 是無線電應用程式提供的任意字串,用於強加一個唯一的(因此給定的ID 僅指向一個項目)和穩定的(因此給定的項目在整個會話中具有相同的ID)值,用於標識給定的電台。 URI 將具有明確定義的模式。簡而言之,ProgramSelector 的 URI 化形式。雖然這保留了唯一性屬性,但它不一定是穩定的,儘管當電台移動到不同頻率時它可能會改變。

根據設計,不使用onPlayFromSearch 。用戶端(配套應用程式)負責從 MediaBrowser 樹中選擇搜尋結果。將這一責任轉移到廣播應用程式會增加複雜性,需要關於字串查詢應如何顯示的正式合同,並導致不同硬體平台上的用戶體驗不均勻。

注意:廣播應用程式不包含可用於搜尋未透過 MediaBrowser 介面向用戶端公開的電台名稱的附加資訊。

跳到下一個或上一個電台取決於當前上下文:

  • 當應用程式調至收藏夾清單中的某個電台時,該應用程式可以移至收藏夾清單中的下一個電台。
  • 收聽節目清單中的電台可能會導致調諧到根據頻道編號排序的下一個可用電台。
  • 即使沒有廣播訊號,收聽任意頻道也可能會導致調諧到下一個實體頻道。

無線電應用程式處理這些操作。

錯誤處理

TransportControls操作(播放、停止和下一個)不提供有關操作是否成功的回饋。指示錯誤的唯一方法是將 MediaSession 狀態設為STATE_ERROR並帶有錯誤訊息。

無線電應用程式必須處理這些操作並執行它們或設定錯誤狀態。如果不立即執行播放指令,則在執行指令時,播放狀態應變更為STATE_CONNECTING (在直接調諧的情況下)或STATE_SKIPPING_TO_PREVIOUSNEXT

客戶端應該觀察PlaybackState並驗證會話是否將目前程式變更為所要求的或進入錯誤狀態。 STATE_CONNECTING不得超過 30 秒。然而,直接調諧到給定的 AM/FM 頻率應該會執行得更快。

新增和刪除收藏夾

MediaSession 具有評級支持,可用於控制收藏夾。使用RATING_HEART類型的評級呼叫onSetRating會將目前調諧的電台新增至收藏夾清單或從收藏夾清單中刪除。

與傳統預設相反,當每個保存的收藏夾被分配到一個數字槽(通常為 1 到 6)時,模型假定無序且無界的收藏夾列表。因此,基於預設的系統將與onSetRating操作不相容。

MediaSession API 的限制是只能新增或刪除目前調諧到的電台。例如,必須先選擇項目才能刪除。這只是 MediaBrowser 用戶端(例如配套應用程式)的限制。廣播應用程式沒有類似的限制。當應用程式不支援收藏夾時,此部分是可選的。

媒體瀏覽器

為了表示哪些頻率或實體頻道名稱(當調諧到任意頻道適合給定無線電技術時)對於給定區域有效,列出了每個頻段的所有有效頻道(頻率)。在美國地區,這相當於 87.8 至 108.0 MHz 範圍內的 101 個 FM 頻道(使用 0.2MHz 間隔)和 530 至 1700 kHz 範圍內的 117 個 AM 頻道(使用 10kHz 間隔)。由於高清廣播使用相同的頻道空間,因此不單獨介紹。

目前可用的廣播節目清單是平坦的,因為這不允許顯示方案,例如按直接音訊廣播 (DAB) 整體進行分組。

收藏夾清單中的條目可能無法調整。例如,如果給定的程序超出範圍。廣播應用程式可能會也可能不會偵測是否可以預先調諧到該條目。如果是這樣,它可能不會將該條目標記為可播放。

為了識別頂級資料夾,應用了藍牙使用的相同機制。也就是說, MediaDescription物件的 Extras 套件包含特定於調諧器的字段,就像藍牙對EXTRA_BT_FOLDER_TYPE所做的那樣。對於廣播電台,這會導致在公共 API 中定義以下新欄位:

  • EXTRA_BCRADIO_FOLDER_TYPE = "android.media.extra.EXTRA_BCRADIO_FOLDER_TYPE" 。以下值之一:
    • BCRADIO_FOLDER_TYPE_PROGRAMS = 1 。目前可用的程式。
    • BCRADIO_FOLDER_TYPE_FAVORITES = 2 。收藏夾。
    • BCRADIO_FOLDER_TYPE_BAND = 3 。給定頻段的所有實體頻道。

    無需定義任何特定於無線電的自訂元資料字段,因為所有相關資料都適合現有的MediaBrowser.MediaItem方案:

    • 程式名稱(RDS PS、DAB 服務名稱)。 MediaDescription.getTitle
    • 調頻頻率。 URI(請參閱ProgramSelector )或MediaDescription.getTitle (如果條目位於BROADCASTRADIO_FOLDER_TYPE_BAND資料夾中)。
    • 無線電特定標識符(RDS PI、DAB SId)。 MediaDescription.getMediaUri解析為 ProgramSelector。

    通常,不需要取得目前節目或收藏清單上的條目的 FM 頻率(因為客戶端應該對媒體 ID 進行操作)。但是,如果出現這種需求(例如,出於顯示目的),它會出現在 URI 中並且可以解析為ProgramSelector 。也就是說,不建議使用 URI 來選擇目前會話中的項目。有關詳細信息,請參閱ProgramSelector

    為了避免效能或活頁夾相關問題,MediaBrowser 服務必須支援分頁:

    注意:預設情況下,分頁是在onLoadChildren()變體中預設實現的,無需選項處理。

    所有類型清單(原始頻道、找到的節目和收藏夾)中的相關條目可能具有不同的 mediaId(這取決於廣播應用程式;支援庫將使它們不同)。大多數情況下,原始頻道和找到的節目(不含RDS 的FM 除外)之間的URI(以節目選擇器形式)不同,但找到的節目和收藏夾之間的URI 基本上相同(例如,更新AF時除外)。

    不同類型清單中的條目具有不同的 mediaId,可以對它們採取不同的操作。您可以在onSkipToNext上遍歷「收藏夾」列表或「所有程式」列表,具體取決於最近選擇的MediaItem的資料夾(請參閱MediaSession )。

    特殊調音動作

    節目清單使用戶能夠調諧到特定電台,但不允許用戶提出諸如「調諧到 FM」之類的一般請求,這可能會導致調諧到 FM 頻段上最近收聽的電台。

    為了支援此類操作,某些頂級目錄設定了FLAG_PLAYABLE標誌(以及資料夾的FLAG_BROWSABLE標誌)。

    行動調至如何發行
    播放廣播任何廣播頻道startService(ACTION_PLAY_BROADCASTRADIO)

    或者

    playFromMediaId(MediaBrowser. getRoot() )
    播放調頻任意 FM 頻道從 FM 頻段的mediaId播放。

    調至哪個節目由應用程式決定。這通常是給定清單中最近調到的頻道。有關ACTION_PLAY_BROADCASTRADIO的詳細信息,請參閱一般播放意圖

    發現和服務連接

    PackageManager可以直接找到服務廣播廣播樹的MediaBrowserService。為此,請使用ACTION_PLAY_BROADCASTRADIO意圖(請參閱一般播放意圖)和MATCH_SYSTEM_ONLY標誌呼叫resolveService 。若要尋找所有提供廣播服務的服務(可能不只一項;例如,單獨的 AM/FM 和衛星),請使用queryIntentServices

    已解析的服務也處理android.media.browse.MediaBrowserService綁定意圖。這已通過 GTS 驗證。

    若要連線到選取的 MediaBrowserService,請為給定的服務元件建立MediaBrowser實例並connect 。建立連線後,可以透過getSessionToken取得 MediaSession 的句柄。

    Radio 應用程式可以限制允許在其服務的onGetRoot實作中連接的用戶端套件。該應用程式應允許系統應用程式在不列入白名單的情況下進行連接。有關白名單的詳細信息,請參閱接受助手應用程式包和簽名

    如果特定於來源的應用程式(例如廣播應用程式)安裝在沒有此類來源支援的裝置上,它仍會將自己宣傳為處理ACTION_PLAY_BROADCASTRADIO意圖,但其 MediaBrowser 樹不​​會包含特定於廣播的標籤。因此,願意檢查給定來源在設備上是否可用的客戶端必須:

    1. 發現廣播服務(為ACTION_PLAY_BROADCASTRADIO呼叫resolveService )。
    2. 建立MediaBrowser ,然後連接到它。
    3. 使用EXTRA_BCRADIO_FOLDER_TYPE extra 確定MediaItem是否存在。

    注意:在大多數情況下,用戶端必須掃描所有可用的 MediaBrowser 樹以偵測給定裝置的所有可用來源。

    樂團名稱

    帶區清單由一組頂層目錄表示,其資料夾類型標記設定為BCRADIO_FOLDER_TYPE_BAND 。他們的MediaItem標題是代表樂團名稱的本地化字串。在大多數情況下,它與英文翻譯相同,但客戶不能依賴這種假設。

    為了提供尋找某些頻段的穩定機制,為頻段資料夾新增了一個額外的標籤EXTRA_BCRADIO_BAND_NAME_EN 。這是樂團的非本地化名稱,只能採用以下預定義值之一:

    • AM
    • FM
    • DAB

    如果樂團不在此列表中,則不應設定樂團名稱標籤。但是,如果樂隊在列表中,則它必須設定標籤。高清廣播不會列舉單獨的頻段,因為它使用與 AM/FM 相同的基礎媒體。

    一般遊戲意圖

    每個專用於播放給定來源(如收音機或 CD)的應用程式都必須處理一般播放意圖,以開始播放可能從非活動狀態(例如,啟動後)的某些內容。如何選擇要播放的內容取決於應用程序,但通常是最近播放的廣播節目或 CD 曲目。為每個音訊來源定義了單獨的意圖:

    • android.car.intent.action.PLAY_BROADCASTRADIO
    • android.car.intent.action.PLAY_AUDIOCD :CD-DA 或 CD-Text
    • android.car.intent.action.PLAY_DATADISC :光學資料光碟,如 CD/DVD,但不是 CD-DA(可能是混合模式 CD)
    • android.car.intent.action.PLAY_AUX :不指定哪個AUX埠
    • android.car.intent.action.PLAY_BLUETOOTH
    • android.car.intent.action.PLAY_USB :不指定哪個USB設備
    • android.car.intent.action.PLAY_LOCAL :本地媒體儲存(內建快閃記憶體)

    選擇意圖用於通用播放命令,因為它們同時解決了兩個問題:通用播放命令本身和服務發現。具有這種意圖的額外好處是可以在不開啟 MediaBrowser 會話的情況下執行這種簡單的操作。

    服務發現其實是這些意圖解決的更重要的問題。透過這種方式,服務發現過程變得簡單且明確(請參閱發現和服務連接)。

    為了使某些客戶端實作更容易,有一種發出此類 Play 命令的替代方法(也必須由廣播應用程式實現):使用根節點的 rootId(用作 mediaId)發出playFromMediaId 。雖然根節點並不意味著可播放,但其 rootId 是任意字串,可以將其用作 mediaId。然而,客戶不需要理解這種細微差別。

    節目選擇器

    雖然mediaId足以從MediaBrowserService選擇通道,但它會綁定到會話並且在提供者之間不一致。在某些情況下,客戶端可能需要絕對指標(例如絕對頻率)來在會話和裝置之間維護它。

    在數位無線電廣播時代,裸露的頻率不足以調諧到特定電台。因此,請使用ProgramSelector調諧到類比或數位頻道。 ProgramSelector由兩個部分組成:

    • 主要標識符。給定廣播電台的唯一且穩定的標識符,不會改變,但可能不足以調諧到該電台。例如,RDS PI 代碼,在美國可能會被翻譯為呼號。
    • 輔助標識符。對於調諧到該電台(例如頻率)有用的附加標識符,可能包括來自其他無線電技術的標識符。例如,DAB 站可能具有類比廣播回退。

    若要讓ProgramSelector適應基於MediaBrowserMediaSession的解決方案,請定義 URI 架構以進行序列化。該架構定義如下:

    broadcastradio://program/<primary ID type>/<primary ID>?
    <secondary ID type>=<secondary ID>&<secondary ID type>=<secondary ID>
    

    在此範例中,次要標識符部分(在問號 ( ? ) 之後)是可選的,可以將其刪除以提供用作mediaId的穩定標識符。例如:

    • broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=88500&AMFM_FREQUENCY=103300
    • broadcastradio://program/AMFM_FREQUENCY/102100
    • broadcastradio://program/DAB_SID_EXT/14895264?RDS_PI=1234

    program的權威部分(又稱主機)為未來的方案擴展提供了一定的空間。識別符類型字串在IdentifierType的 HAL 2.x 定義中精確指定為其名稱,值格式為十進位或十六進位(帶0x前綴)數字。

    所有供應商特定的識別碼均由VENDOR_前綴表示。例如, VENDOR_0表示VENDOR_STARTVENDOR_1表示VENDOR_START加 1。此類 URI 特定於產生它們的無線電硬件,不能在不同 OEM 製造的設備之間傳輸。

    這些 URI 必須指派給頂級廣播資料夾下的每個 MediaItem。此外,MediaSession 必須同時支援playFromMediaIdplayFromUri 。然而,URI 主要用於無線電元資料擷取(例如 FM 頻率)和持久性儲存。無法保證 URI 可用於所有媒體項目(例如,當框架尚不支援主 ID 類型時)。另一方面,媒體 ID 始終有效。不建議用戶端使用 URI 從目前 MediaBrowser 會話中選擇項目。相反,請使用playFromMediaId 。也就是說,它對於服務應用程式來說不是可選的,並且缺少的 URI 是為合理的情況保留的。

    初始設計在方案部分之後使用單一冒號而不是://序列。但是,對於絕對分層 URI 引用, android.net.Uri不支援前者。

    其他來源類型

    其他音訊來源可以類似處理。例如,輔助輸入和音訊 CD 播放器。

    單一應用程式可以提供多種類型的來源。在這種情況下,建議您為每種類型的來源建立單獨的 MediaBrowserService。即使在具有多個服務來源/MediaBrowserServices 的設定中,也強烈建議在單一應用程式中使用單一 MediaSession。

    音訊CD

    與音訊 CD 類似,為此類磁碟提供服務的應用程式將透過單一可瀏覽條目(或更多,如果系統有 CD 換碟機)公開 MediaBrowser,而該條目將包含給定 CD 的所有曲目。如果系統不了解每張 CD 上的曲目(例如,當所有磁碟一次插入盒式磁帶並且不會全部讀取時),則整個磁碟的 MediaItem 將只是PLAYABLE ,而不是BROWSABLEPLAYABLE 。如果給定插槽中沒有磁碟,則該項目既不可PLAYABLE也無法BROWSABLE (但每個插槽必須始終存在於樹中)。

    音訊 CD 樹結構
    圖 3.音訊 CD 樹結構

    這些條目將以與廣播電台資料夾類似的方式標記;它們將包含 MediaDescription API 中定義的其他額外欄位:

    • EXTRA_CD_TRACK :對於音訊 CD 上的每個MediaItem ,從 1 開始的軌道編號。
    • EXTRA_CD_DISK :從 1 開始的磁碟編號。

    對於啟用 CD-Text 的系統和相容磁碟,頂級 MediaItem 將具有磁碟標題。類似地,曲目的 MediaItems 將具有曲目的標題。

    輔助輸入

    提供輔助輸入的應用程式公開一個 MediaBrowser 樹,其中包含表示 AUX 輸入連接埠的單一條目(或多個條目,當存在多個連接埠時)。對應的 MediaSession 取得其 mediaId 並在收到playFromMediaId請求後切換到該來源。

    AUX 樹狀結構
    圖 4. AUX 樹狀結構

    每個 AUX MediaItem 條目都會有一個額外欄位EXTRA_AUX_PORT_NAME ,設定為連接埠的非本地化名稱,不帶「AUX」短語。例如,“AUX 1”應設定為“1”,“AUX front”應設定為“front”,“AUX”應設定為空字串。在非英語語言環境中,名稱標籤將保持相同的英語字串。與EXTRA_BCRADIO_BAND_NAME_EN不同的是,這些值是 OEM 定義的,並且不受預先定義列表的限制。

    如果硬體可以偵測到連接到AUX連接埠的設備,則只有在連接輸入時,硬體應標記為PLAYABLE媒體。如果沒有連接到此端口,則仍應列出(但不能PLAYABLE )硬體。如果硬體沒有這種功能,則必須始終將MediaItem設為PLAYABLE

    額外字段

    定義以下欄位:

    • EXTRA_CD_TRACK = "android.media.extra.CD_TRACK"
    • EXTRA_CD_DISK = "android.media.extra.CD_DISK"
    • EXTRA_AUX_PORT_NAME = "android.media.extra.AUX_PORT_NAME"

    客戶端需要查看具有EXTRA_CD_DISKEXTRA_AUX_PORT_NAME Extra Field設定的元素的頂級媒體資訊。

    詳細的例子

    以下範例介紹了此設計一部分的來源類型的MediaBrowser樹結構。

    廣播無線電MediaBrowserService(處理ACTION_PLAY_BROADCASTRADIO ):

    • 電台(browsable) EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_PROGRAMS
      • BBC ONE(可玩)URI: broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=90500
      • ABC 88.1(可玩)URI: broadcastradio://program/RDS_PI/5678?AMFM_FREQUENCY=88100
      • ABC 88.1 HD1(可播放)URI: broadcastradio://program/HD_STATION_ID_EXT/158241DEADBEEF?AMFM_FREQUENCY=88100&RDS_PI=5678
      • ABC 88.1 HD2(可播放)URI: broadcastradio://program/HD_STATION_ID_EXT/158242DEADBEFE
      • 90.5 fm(可玩) - 無rdsuri的FM: broadcastradio://program/AMFM_FREQUENCY/90500
      • 620 AM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/620
      • BBC ONE(可玩)URI: broadcastradio://program/DAB_SID_EXT/1E24102?RDS_PI=1234
    • EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_FAVORITES (可瀏覽,可玩)
      • BBC ONE(可玩)URI: broadcastradio://program/RDS_PI/1234?AMFM_FREQUENCY=101300
      • BBC兩個(不播放)URI: broadcastradio://program/RDS_PI/1300?AMFM_FREQUENCY=102100
    • AM(Browsable,可播放): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="AM"
      • 530 AM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/530
      • 540 AM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/540
      • 550 AM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/550
    • FM(Browsable,可玩): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="FM"
      • 87.7 FM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/87700
      • 87.9 FM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/87900
      • 88.1 FM(可玩)URI: broadcastradio://program/AMFM_FREQUENCY/88100
    • dab(可玩): EXTRA_BCRADIO_FOLDER_TYPE=BCRADIO_FOLDER_TYPE_BANDEXTRA_BCRADIO_BAND_NAME_EN="DAB"

    音訊CD MediaBrowserService(處理ACTION_PLAY_AUDIOCD ):

    • 光碟1(可玩) EXTRA_CD_DISK=1
    • 光碟2(可瀏覽,可玩) EXTRA_CD_DISK=2
      • 曲目1(可玩) EXTRA_CD_TRACK=1
      • 曲目2(可玩) EXTRA_CD_TRACK=2
    • 我的音樂CD(可瀏覽,可玩) EXTRA_CD_DISK=3
      • 一個人一個人(可玩) EXTRA_CD_TRACK=1
      • reise,reise(可玩) EXTRA_CD_TRACK=2
    • 空插槽4(不播放) EXTRA_CD_DISK=4

    Aux MediaBrowserService(處理ACTION_PLAY_AUX ):

    • Aux Front(可玩) EXTRA_AUX_PORT_NAME="front"
    • 輔助後(可播放) EXTRA_AUX_PORT_NAME="rear"