編寫:huanglizhuo - 原文:http://developer.android.com/training/tv/playback/now-playing.html
TV應用允許用戶在使用其他應用時後臺播放音樂或其他媒體。如果我們的應用程序允許後臺,它必須要為用戶提供返回該應用暫停音樂或切換到一個新的歌曲的方法。 Android框架允許TV應用通過在主屏幕上顯示正在播放卡做到這一點。
正在播放卡片是系統的組建,它可以在推薦的行上顯示正在播放的媒體會話它包括了媒體元數據,如專輯封面,標題和應用程序圖標。當用戶選擇它,系統將打開擁有該會話的應用程序。
這節課將演示如何使用 MediaSession 類實現正在播放卡片。
##開啟媒體會話
一個播放應用可以作為 activity 或者 service 運行。 service 是當 activity 結束時依然可以後臺播放的。在這節討論中,媒體播放應用是假設在 MediaBrowserService 下運行的。
在service的onCreate()方法中創建一個新的[ MediaSession ](http://developer.android.com/reference/android/media/session/MediaSession.html#MediaSession(android.content.Context, java.lang.String)),設置適當的回調函數和標誌,並設置 MediaBrowserService 令牌。
mSession = new MediaSession(this, "MusicService");
mSession.setCallback(new MediaSessionCallback());
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
// for the MediaBrowserService
setSessionToken(mSession.getSessionToken());
**注意:**正在播放卡片只有在媒體會話設置了FLAG_HANDLES_TRANSPORT_CONTROLS標誌時在可以顯示。
##顯示正在播放卡片
如果會話是系統最高優先級的會話那麼正在播放卡片將在setActivity(true)調用後顯示。同時我們的應用必須像在Managing Audio Focus一節中那樣請求音頻焦點。
private void handlePlayRequest() {
tryToGetAudioFocus();
if (!mSession.isActive()) {
mSession.setActive(true);
}
...
如果另一個應用發起媒體播放請求並調用setActivity(false)後這個卡片將從主屏上移除。
##更新播放狀態
正如任何媒體的應用程序,在 MediaSession 中更新播放狀態,使卡片可以顯示當前的元數據,如在下面的例子:
private void updatePlaybackState() {
long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
position = mMediaPlayer.getCurrentPosition();
}
PlaybackState.Builder stateBuilder = new PlaybackState.Builder()
.setActions(getAvailableActions());
stateBuilder.setState(mState, position, 1.0f);
mSession.setPlaybackState(stateBuilder.build());
}
private long getAvailableActions() {
long actions = PlaybackState.ACTION_PLAY |
PlaybackState.ACTION_PLAY_FROM_MEDIA_ID |
PlaybackState.ACTION_PLAY_FROM_SEARCH;
if (mPlayingQueue == null || mPlayingQueue.isEmpty()) {
return actions;
}
if (mState == PlaybackState.STATE_PLAYING) {
actions |= PlaybackState.ACTION_PAUSE;
}
if (mCurrentIndexOnQueue > 0) {
actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
}
if (mCurrentIndexOnQueue < mPlayingQueue.size() - 1) {
actions |= PlaybackState.ACTION_SKIP_TO_NEXT;
}
return actions;
}
##顯示媒體元數據
為當前正在播放通過setMetadata()方法設置 MediaMetadata 。.這個方法可以讓我們為正在播放卡提供有關軌道,如標題,副標題,和各種圖標等信息。下面的例子假設我們的播放數據存儲在自定義的MediaData類中。
private void updateMetadata(MediaData myData) {
MediaMetadata.Builder metadataBuilder = new MediaMetadata.Builder();
// To provide most control over how an item is displayed set the
// display fields in the metadata
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE,
myData.displayTitle);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE,
myData.displaySubtitle);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI,
myData.artUri);
// And at minimum the title and artist for legacy support
metadataBuilder.putString(MediaMetadata.METADATA_KEY_TITLE,
myData.title);
metadataBuilder.putString(MediaMetadata.METADATA_KEY_ARTIST,
myData.artist);
// A small bitmap for the artwork is also recommended
metadataBuilder.putString(MediaMetadata.METADATA_KEY_ART,
myData.artBitmap);
// Add any other fields you have for your data as well
mSession.setMetadata(metadataBuilder.build());
}
##響應用戶的動作
當用戶選擇正在播放卡片時,系統打開應用並擁有會話。如果我們的應用在setSessionActivity()有PendingIntent要傳遞,系統將會像下面演示的那樣開啟activity。如果不是,則系統默認的Intent打開。您指定的活動必須提供播放控制,允許用戶暫停或停止播放。
Intent intent = new Intent(mContext, MyActivity.class);
PendingIntent pi = PendingIntent.getActivity(context, 99 /*request code*/,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
mSession.setSessionActivity(pi);