Android 音樂播放器自己來 — Day 8 播放器架構實作 (1) — MediaBrowseService 實作

fantasy1022
毅想世界
Published in
Feb 12, 2021

今天就開始實作音樂播放器整體架構了,還記得在第一天最後介紹到的架構圖嗎,這篇會從MediaBrowserService 開始實作,先從比較底層元件開始實作,播歌時需要 Android 架構的 Service 元件,讓音樂在背景能繼續播放,首先先 import androidx media 相關的 library。

implementation 'androidx.media:media:1.1.0'

實作的 Service 繼承 MediaBrowserServiceCompat,為官方為了播歌和瀏覽歌曲實作的 Service,並搭配之後會使用到 MediaBrowser,實作 Client / Server 架構。

同時在 AndroidManifest 內要註冊 Service,就像是 Activity 一樣,其中比較特別的是要加入 intent-filter,和 Android 系統註冊, App 有 MediaBrowser 的功能。

繼承 MediaBrowserServiceCompat 後,有兩個 abstract function 是要實作的:

首先是 onLoadChildren 屬於瀏覽歌曲相關,可以看到會傳入 parentId,然後再將 result 傳出,在 uamp 專案內點擊專輯後,會顯示專輯內的歌曲,收到 Id 後,去 local 的 repository 尋找相關的歌曲,然後將結果透過 result.sendResult(items) 回傳,但這個 function 目前用不到,因此就先不實作。

onGetRoot 有很重要的功能,可以決定要不要讓其他 App 或是服務連接上,連上後可以瀏覽音樂檔案並進行音樂播放相關的操作,聽起來有點抽象,就像是第一天提到的可以透過手錶或是其他 App 來控制或是取得相關的音樂資料,就是透過這個 function。

那我們要怎麼決定規則呢?先來看 uamp 專案的寫法,會有一個進行確認的 function,裡面仔細看還蠻複雜的,會判一些可以連接的 Package 名稱的白名單 (Android Auto, WearOS, Android Auto Simulator, Google Assistant),還會判斷 Sign key 的 signature 是否符合。用 uid 可以判斷是否為自己本身得 App 想要連接或是系統端要連:

那如果判斷是非預期的呼叫端呢,從 uamp 上的註解可以得知有兩個處理方式,一個方是回傳空的 BrowserRoot,就不能瀏覽音樂檔案,但可以進行播放的操作,另外一個方式直接回傳 null,完全不能連上,也就不能控制音樂的播放行為了。

目前先採用比較簡單的做法,只判斷是否為自己本身的 App 端呼叫,如果非自己本身的 App 呼叫,在 debug 版才能連上,release 版就先連不上。之後有其他的服務(ex: Google Assistant)有需要連上,就再來這邊加入。

程式碼在這邊,分支名稱(day8_media_browser_service):

--

--