MediaProvider 模組

MediaProvider 模組會最佳化索引中繼資料 (SD 卡和 USB 裝置中的音訊、影片和圖片),並透過 MediaStore 公開 API 將資料提供給應用程式。為維護使用者隱私,MediaProvider 模組會強制執行 Android 10 中導入的範圍儲存空間安全模型,包括遮蓋敏感的位置中繼資料。這個模組可更新,因此 Android 能更快因應安全性問題 (保護敏感的使用者資料),並快速新增媒體格式 (為使用者和開發人員提供一致性)。

Android 10 的變更

Android 10 推出多項改良功能,可識別及擷取媒體檔案中的資料,具體來說:

  • 使用檔案 MIME 類型的前半部分判斷檔案內容類型。 舉例來說,作業系統知道 image/pngimage/x-newly-invented-format 都是圖片,因此可以準確向使用者說明相關權限。

  • 僅使用副檔名判斷 MIME 類型 (且不使用內容嗅探,以免發生安全性問題)。

  • 使用上游 Debian Linux 和 Android 對應,判斷任意檔案的 MIME 類型。

  • video/*audio/* 檔案 (透過 MediaMetadataRetriever) 和 image/* 檔案 (透過 ExifInterface) 傳回相關資料。

Android 11 的變更

在 Android 11 中,MediaProvider 模組以 Android 10 的變更為基礎,並進行下列改良:

  • 改善索引功能。MediaProvider 模組現在會透過比對可用的中繼資料與 MediaStore 公用 API,為中繼資料建立索引。變更內容包括:

    • 新增 is_favorite 欄和 QUERY_ARG_MATCH_FAVORITE 引數,讓相簿風格的應用程式能根據這個欄位快速篩選媒體。

    • 建立色彩空間中繼資料的索引。

    • 新的 is_trashed 欄和 QUERY_ARG_MATCH_TRASHED 引數,可讓圖庫樣式的應用程式根據這個資料欄進行篩選。

    • 新增 API,可透過單一使用者對話方塊提示大量修改多個項目,包括 createDeleteRequest()createFavoriteRequest()createTrashRequest()createWriteRequest()

    • 新增 GENERATION_ADDEDGENERATION_MODIFIED 欄,可快速且可靠地偵測自上次同步處理點以來發生的變更。

    • 新的 GROUP BY 公用 API,可用於上述未提及的其他中繼資料欄。

  • 改善 ExifInterface,可從 PNG 和 WebP 容器擷取中繼資料。

  • 改善 SystemUI,可在螢幕截圖中寫入 DateTimeOriginal 中繼資料。

此外,您現在可以新增媒體格式、標示應建立索引的儲存裝置,甚至取代 MTP 堆疊,藉此自訂 MediaProvider。詳情請參閱「自訂」。

模組邊界

Android 11 會將 packages/providers/MediaProvider 中的所有程式碼遷移至新位置,但 MTP 相關邏輯是例外。此外,frameworks/base/core/java/android/provider/MediaStore.java 現在位於 packages/providers/MediaProvider 的模組邊界「內」。

套件格式

MediaProvider 模組採用 APK-in-APEX 格式。

依附元件

MediaProvider 依附元件與自訂項目有關 (也就是說,如果您自訂 MediaProvider,必須確保實作項目符合與自訂項目相關聯的依附元件)。

  • 使用自訂或非標準媒體檔案格式 (例如由特定廠商的「相機」應用程式產生的格式) 時,您必須向 MimeUtils 和 Media Extractor 模組註冊每個自訂格式,才能讓 MediaProvider 建立索引。

  • 如要確保 MediaProvider 為 StorageManagerService 實作中使用的自訂儲存裝置集 (例如 SD 卡插槽和 USB 連接埠) 編製索引,請設定 VolumeInfo.MOUNT_FLAG_INDEXABLE 標記。

  • 使用自訂 (非 AOSP) MTP 實作時,請確保實作僅依賴公開和系統 API,以便與 MediaStore 互動。

自訂

您可以新增媒體格式、影響要建立索引的儲存裝置、取代 MTP 堆疊,以及排除要建立的預設資料夾。

  • 自訂媒體格式。針對每個新的自訂媒體格式,您必須提供從專屬副檔名到 MIME 類型的對應。強烈建議您按照 IANA 註冊程序操作。

    • 您無法重新定義 AOSP 中已定義的副檔名或 MIME 類型。

    • 如果是 video/*audio/* 檔案,MediaProvider 會繼續諮詢 MediaMetadataRetriever。使用 Android 10 媒體擷取器,傳回自訂格式的中繼資料。

    • 對於 image/* 檔案,MediaProvider 會繼續以 Exif 為中繼資料標準。您可以擴充 android.media.ExifInterface,擷取並傳回任何自訂圖片格式的 Exif 中繼資料。

  • 儲存裝置索引標記。MediaProvider 會為 StorageManager.getStorageVolumes() 傳回的所有磁碟區建立索引,其中 StorageVolume.getMediaStoreVolumeName() 不為空值。您可以自訂傳回的磁碟區清單,影響索引作業的範圍,但建議不要納入暫時性磁碟區 (例如 USB OTG 磁碟機)。

  • MTP 堆疊更換。Android 11 會將 MTP 堆疊完全放在模組邊界之外,並確保其可搭配公開 API 運作。

  • 預設資料夾排除清單。MediaProvider 會為新掛接的儲存空間磁碟區建立預設資料夾: Music/Podcasts/Ringtones/Alarms/Notifications/Pictures/Movies/Download/DCIM/Documents/Audiobooks/Recordings/ (Android 11 以下版本不支援 Recordings/ 目錄) 。在 Android 12 以上版本中,原始設備製造商 (OEM) 可以提供不區分大小寫的資料夾排除清單,供 MediaProvider 在建立預設資料夾時略過。舉例來說,這些資料夾 (例如 Download/ 資料夾) 可能仍會由外部邏輯建立。

如要新增排除清單,請使用config_foldersToSkipInDefaultCreation 執行階段資源疊加 (RRO)。以下範例說明如何排除 Notifications/Ringtones/ 預設資料夾:

<string-array name="config_foldersToSkipInDefaultCreation" translatable="false">
    <item>"Notifications"</item>
    <item>"Ringtones"</item>
</string-array>

測試

您可以透過下列測試驗證 MediaProvider 的功能:

  • 如要驗證 MediaStore 公用 API 的功能,請使用 Android 相容性測試套件 (CTS) 的 CtsProviderTestCases 套件中的測試。

  • 如要驗證 MediaProvider 內部功能,請使用 MediaProviderTests 中的測試。

如要同時執行兩組測試,請使用下列 atest 指令:

atest --test-mapping packages/providers/MediaProvider