導入媒體工作階段

在應用程式準備播放媒體時建立 MediaSession。下列程式碼片段 是如何設定適當的回呼和標記的範例:

KotlinJava
session = MediaSession(this, "MusicService").apply {
    setCallback
(MediaSessionCallback())
    setFlags
(
           
MediaSession.FLAG_HANDLES_MEDIA_BUTTONS or MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS
   
)
}
session = new MediaSession(this, "MusicService");
session
.setCallback(new MediaSessionCallback());
session
.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
       
MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);

啟動媒體工作階段

請務必在播放開始時呼叫 setActive(true)。您的應用程式也必須要求音訊焦點,如下所述: 管理音訊焦點。這些步驟 如以下範例所示:

KotlinJava
private fun handlePlayRequest() {

    tryToGetAudioFocus
()

   
if (!session.isActive) {
        session
.isActive = true
   
}
   
...
}
private void handlePlayRequest() {

    tryToGetAudioFocus
();

   
if (!session.isActive()) {
        session
.setActive(true);
   
}
   
...
}

更新播放狀態

更新 MediaSession 中的播放狀態,以反映目前媒體的狀態:

KotlinJava
private fun updatePlaybackState() {
   
val position: Long =
            mediaPlayer
                   
?.takeIf { it.isPlaying }
                   
?.currentPosition?.toLong()
                   
?: PlaybackState.PLAYBACK_POSITION_UNKNOWN

   
val stateBuilder = PlaybackState.Builder()
           
.setActions(getAvailableActions()).apply {
                setState
(mState, position, 1.0f)
           
}
    session
.setPlaybackState(stateBuilder.build())
}

private fun getAvailableActions(): Long {
   
var actions = (PlaybackState.ACTION_PLAY_PAUSE
            or
PlaybackState.ACTION_PLAY_FROM_MEDIA_ID
            or
PlaybackState.ACTION_PLAY_FROM_SEARCH)

    playingQueue
?.takeIf { it.isNotEmpty() }?.apply {
        actions
= if (mState == PlaybackState.STATE_PLAYING) {
            actions or
PlaybackState.ACTION_PAUSE
       
} else {
            actions or
PlaybackState.ACTION_PLAY
       
}
       
if (currentIndexOnQueue > 0) {
            actions
= actions or PlaybackState.ACTION_SKIP_TO_PREVIOUS
       
}
       
if (currentIndexOnQueue < size - 1) {
            actions
= actions or PlaybackState.ACTION_SKIP_TO_NEXT
       
}
   
}
   
return actions
}
private void updatePlaybackState() {
   
long position = PlaybackState.PLAYBACK_POSITION_UNKNOWN;
   
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
        position
= mediaPlayer.getCurrentPosition();
   
}
   
PlaybackState.Builder stateBuilder = new PlaybackState.Builder()
           
.setActions(getAvailableActions());
    stateBuilder
.setState(mState, position, 1.0f);
    session
.setPlaybackState(stateBuilder.build());
}

private long getAvailableActions() {
   
long actions = PlaybackState.ACTION_PLAY_PAUSE |
           
PlaybackState.ACTION_PLAY_FROM_MEDIA_ID |
           
PlaybackState.ACTION_PLAY_FROM_SEARCH;
   
if (playingQueue == null || playingQueue.isEmpty()) {
       
return actions;
   
}
   
if (mState == PlaybackState.STATE_PLAYING) {
        actions
|= PlaybackState.ACTION_PAUSE;
   
} else {
        actions
|= PlaybackState.ACTION_PLAY;
   
}
   
if (currentIndexOnQueue > 0) {
        actions
|= PlaybackState.ACTION_SKIP_TO_PREVIOUS;
   
}
   
if (currentIndexOnQueue < playingQueue.size() - 1) {
        actions
|= PlaybackState.ACTION_SKIP_TO_NEXT;
   
}
   
return actions;
}

更新媒體中繼資料

使用 setMetadata() 方法設定 MediaMetadata。每個播放的物件只會呼叫此方法一次。這可讓您向媒體工作階段提供媒體相關資訊,包括標題、副標題、藝人、圖片等。以下範例是針對音樂量身打造,並假設曲目資料儲存在自訂資料類別 MediaData 中:

KotlinJava
private fun updateMetadata(myData: MediaData) {
   
val metadataBuilder = MediaMetadata.Builder().apply {
       
// To provide most control over how an item is displayed set the
       
// display fields in the metadata
        putString
(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, myData.displayTitle)
        putString
(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, myData.displaySubtitle)
        putString
(MediaMetadata.METADATA_KEY_DISPLAY_ICON_URI, myData.artUri)
       
// And at minimum the title and artist for legacy support
        putString
(MediaMetadata.METADATA_KEY_TITLE, myData.title)
        putString
(MediaMetadata.METADATA_KEY_ARTIST, myData.artist)
       
// A small bitmap for the artwork is also recommended
        putBitmap
(MediaMetadata.METADATA_KEY_ART, myData.artBitmap)
       
// Add any other fields you have for your data as well
   
}
    session
.setMetadata(metadataBuilder.build())
}
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
.putBitmap(MediaMetadata.METADATA_KEY_ART,
            myData
.artBitmap);
   
// Add any other fields you have for your data as well
    session
.setMetadata(metadataBuilder.build());
}