1. 簡介
上次更新時間:2020 年 9 月 9 日
在影片播放期間新增 MediaSession 有哪些好處?
媒體工作階段是 Android 平台和媒體應用程式之間的必要連結。這項事件不僅會通知 Android 媒體正在播放,以便將媒體動作轉送至正確的工作階段,還會通知平台正在播放的內容,以及如何控制該內容。
透過應用程式公開 MediaSession 可為使用者帶來多項好處。以下列舉幾個絕佳的範例。
Google 助理
使用者可以透過語音指令與應用程式中的媒體互動,例如「暫停」、「繼續」和「下一首」。您也可以使用媒體的中繼資料,取得目前正在播放的內容。
Android TV
在大型螢幕體驗中,Android TV 應用程式可利用傳統遙控器,為支援 HDMI-CEC 的電視使用者提供服務。透過播放/暫停、停止、下一首和上一首按鈕發出的指令會傳送至應用程式。
螢幕上的媒體控制選項
從 Android 4.0 (API 級別 14) 開始,系統可以存取媒體工作階段的播放狀態和中繼資料。這項功能可讓鎖定畫面顯示媒體控制項和圖片。這項行為會因 Android 版本而異。
背景媒體
即使播放媒體的應用程式在背景執行,您仍可在上述任何情況下控制媒體。
微光 運算
您可以透過媒體提供的資料,說明正在播放的內容和控制方式,讓使用者在不同裝置之間建立連結,以便使用者以各種喜愛的方式與媒體互動。
建構項目
在本程式碼研究室中,您將擴充現有的 Exoplayer 範例,以便新增媒體工作階段支援功能。您的應用程式將會:
- 正確反映媒體工作階段的有效狀態
- 將媒體控制項轉送至 ExoPlayer
- 將佇列中項目的中繼資料傳遞至媒體工作階段
課程內容
- 媒體工作階段為何可為使用者提供更豐富的體驗
- 如何建立媒體工作階段及管理其狀態
- 如何將媒體工作階段連結至 ExoPlayer
- 如何在媒體工作階段的播放佇列中加入項目中繼資料
- 如何新增其他 (自訂) 動作
本程式碼研究室著重於 MediaSession SDK。我們不會對與本主題無關的概念和程式碼區塊多做介紹,但會事先準備好這些程式碼區塊,屆時您只要複製及貼上即可。
軟硬體需求
- 最新版 Android Studio (3.5 以上版本)
- 具備開發 Android 應用程式的基本知識
2. 開始設定
從哪裡開始?
我們要從 ExoPlayer 的主要示範開始。這個示範包含內含畫面上播放控制項的影片,但不會使用媒體工作階段。這對我們來說是個很好的切入點,可以開始新增這些功能!
取得 ExoPlayer 範例
為了快速上手,我們先從 ExoPlayer 範例開始。執行下列程式碼,複製 GitHub 存放區。
git clone https://github.com/google/ExoPlayer.git
開啟示範影片
在 Android Studio 中,開啟 demos/main
下的主要示範專案。
Android Studio 會提示您設定 SDK 路徑。如有任何問題,建議您按照「更新 IDE 和 SDK 工具」中的建議項目操作。
如果系統要求您使用最新版 Gradle,請直接進行更新。
請花點時間瞭解應用程式的設計方式。請注意,這裡有兩個活動:SampleChooserActivity 和 PlayerActivity。我們會在本程式碼研究室的剩餘部分中,使用 PlayerActivity 實際播放媒體,因此請開啟這個類別,並繼續閱讀下一節。
3. 建立媒體工作階段並管理其狀態
建立媒體工作階段
開啟 PlayerActivity.java
。這個類別會建立 ExoPlayer,並管理其功能,例如將影片算繪至螢幕。在這個活動中,我們會將 ExoPlayer 連結至媒體工作階段。
請在類別頂端宣告以下兩個欄位。我們會在本節中使用這些欄位。
private MediaSessionCompat mediaSession;
private MediaSessionConnector mediaSessionConnector;
您必須將「extension-mediasession」專案依附元件新增至模組層級的 build.gradle
,以便支援「Module: demo」:
implementation project(path: ':extension-mediasession')
請注意,如果您將滑鼠游標懸停在解決 MediaSessionConnector 時發生的錯誤上,Android Studio 會自動協助您新增這個依附元件:
最後,請新增下列內容來解決類別匯入問題:
import android.support.v4.media.session.MediaSessionCompat;
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
建立活動時,我們會建立媒體工作階段和媒體工作階段連接器,做為媒體工作階段和 ExoPlayer 之間的中介。
插入這個值的理想位置是建立 ExoPlayer 的位置。在示範應用程式中,我們可以將程式碼附加至 initializePlayer()
的結尾。請務必在播放器例項化後新增這項邏輯!
private void initializePlayer() {
if (player == null) {
...
player = ...
...
mediaSession = new MediaSessionCompat(this, "sample");
mediaSessionConnector = new MediaSessionConnector(mediaSession);
mediaSessionConnector.setPlayer(player);
}
...
}
釋放媒體工作階段
不再需要時釋放媒體工作階段。在 releasePlayer()
中發布 ExoPlayer 時,我們也可以加入下列程式碼:
private void releasePlayer() {
if (mediaSession != null) {
mediaSession.release();
}
...
}
管理媒體工作階段狀態
我們已將媒體工作階段例項化,因此需要確保在使用者與活動互動時,其狀態能正確顯示。
使用者啟動活動時,媒體工作階段應會啟用:
@Override
public void onStart() {
...
if (mediaSession != null) {
mediaSession.setActive(true);
}
}
由於我們的應用程式不會在背景播放媒體,因此必須確保媒體工作階段在使用者離開活動時處於非活動狀態:
@Override
public void onStop() {
super.onStop();
if (mediaSession != null) {
mediaSession.setActive(false);
}
...
}
讓我們執行示範
- 連結 Android 裝置或啟動模擬器。
- 請確認已選取「demo」,以便從 Android Studio 工具列執行。
- 按一下 Android Studio 工具列中的
。
- 應用程式在裝置上啟動後,請選取要播放的影片串流。
- 開始播放後,請嘗試使用下列
adb
指令控制媒體工作階段:
adb shell media dispatch pause
adb shell media dispatch play
adb shell media dispatch play-pause
adb shell media dispatch fast-forward
adb shell media dispatch rewind
- 另外,請瞭解 Android 如何檢視媒體工作階段。特別是,您可以查看動作欄位,瞭解系統支援哪些動作。這裡顯示的數字是動作 ID 的組合,如 PlaybackState 物件中所宣告。如要查看媒體工作階段的執行情形:
adb shell dumpsys media_session
- 如果使用的是實體裝置,且裝置有麥克風,請嘗試喚醒 Google 助理並發出語音指令,例如「暫停」。「繼續」。「快轉 1 分鐘」。
在 Android TV 上執行的 ExoPlayer 範例。
4. 在播放佇列中加入項目的中繼資料
我們現在可以擴充媒體工作階段的支援功能,我們先前已在 initializePlayer()
中建立 MediaSessionConnector。
新增 TimelineQueueNavigator
ExoPlayer 會以時間軸表示媒體結構。如要進一步瞭解這項功能的運作方式,請花點時間閱讀 ExoPlayer 的時間軸物件。透過這個結構,我們可以瞭解內容變更的時間,並在使用者要求時,提供目前播放內容的中繼資料。
為此,我們會定義 TimelineQueueNavigator。找出 initializePlayer()
中的 MediaSessionConnector 例項,並在 mediaSession
初始化後 新增 TimelineQueueNavigator 的實作項目。
mediaSessionConnector.setQueueNavigator(new TimelineQueueNavigator(mediaSession) {
@Override
public MediaDescriptionCompat getMediaDescription(Player player, int windowIndex) {
return new MediaDescriptionCompat.Builder()
.setTitle(player.getCurrentMediaItem().mediaMetadata.title)
.setDescription("MediaDescription description for " + windowIndex)
.setSubtitle("MediaDescription subtitle")
.build();
}
});
如要解決類別匯入問題,請新增下列項目:
import android.support.v4.media.MediaDescriptionCompat;
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator;
請注意,windowIndex
參數會對應至播放佇列中該索引的項目。
新增中繼資料後,你可以測試 Google 助理是否能瞭解正在播放的內容。在 Android TV 上播放影片時,請喚醒 Google 助理,然後詢問「現在播放的是什麼?」
5. 自訂動作
也許您的播放器不支援某些動作,或者您想加入更多支援功能?接下來,我們將進一步探討先前在 initializePlayer()
中建立的媒體工作階段,其中包含 MediaSessionConnector。
宣告支援的動作
請嘗試使用 mediaSessionConnector.setEnabledPlaybackActions()
自訂媒體工作階段支援的動作。
請注意,完整的設定如下:
mediaSessionConnector.setEnabledPlaybackActions(
PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_PLAY
| PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_SEEK_TO
| PlaybackStateCompat.ACTION_FAST_FORWARD
| PlaybackStateCompat.ACTION_REWIND
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SET_REPEAT_MODE
| PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE
);
我們再來看看這項資料如何公開給平台:
- 如同先前所述,開始播放影片。
- 如要瞭解 Android 如何查看媒體工作階段的中繼資料,請執行以下程式碼:
adb shell dumpsys media_session
- 找出含有中繼資料的資料行,並確認標題和說明已納入並與
com.google.android.exoplayer2.demo/sample
建立關聯。
新增其他動作
我們可以透過一些額外動作擴充媒體工作階段。在本節中,我們只會新增字幕支援功能。
支援字幕
在媒體工作階段中加入字幕支援功能,讓使用者可以透過語音切換字幕。在您初始化媒體工作階段連接器的位置,新增下列項目:
mediaSessionConnector.setCaptionCallback(new MediaSessionConnector.CaptionCallback() {
@Override
public void onSetCaptioningEnabled(Player player, boolean enabled) {
Log.d("MediaSession", "onSetCaptioningEnabled: enabled=" + enabled);
}
@Override
public boolean hasCaptions(Player player) {
return true;
}
@Override
public boolean onCommand(Player player, ControlDispatcher controlDispatcher, String command, Bundle extras, ResultReceiver cb) {
return false;
}
}
);
最後,修正所有缺少的匯入內容。
如要測試這項功能,請在 Android TV 上叫出 Google 助理,然後說出「啟用字幕」。請查看 Logcat 訊息,瞭解這項呼叫如何進入您的程式碼。
6. 恭喜
恭喜,您已成功將媒體工作階段新增至範例!
您可以透過以下方式獲得大量功能:
- 新增媒體工作階段、
- 將媒體工作階段連結至 ExoPlayer 的例項
- 新增中繼資料和其他動作。
您現在已瞭解豐富媒體應用程式所需的關鍵步驟,並能為使用者提供更多元化的體驗!
最終 備註
這個程式碼研究室是根據 ExoPlayer 原始碼的範例建立。您不需要從原始碼使用 ExoPlayer,建議您改為提取 ExoPlayer 和 MediaSessionConnector 的依附元件,以便更輕鬆地掌握最新版本。
如要這樣做,只要取代專案依附元件即可,例如:
implementation project(modulePrefix + 'library-core')
implementation project(path: ':extension-mediasession')
從 Maven 存放區提取,例如:
implementation 'com.google.android.exoplayer:exoplayer-core:2.+'
implementation 'com.google.android.exoplayer:extension-mediasession:2.+'