mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Expand MediaItems in session demo instead of just replacing them
When MediaItems are added from the controller, we currently completely replace the item with the one from our database, overriding any potential additional information the controller may have set. Also forward the onAddMediaItems/onSetMediaItems callbacks to common helper methods instead of redirecting them through super methods #minor-release Issue: androidx/media#706 PiperOrigin-RevId: 573799351
This commit is contained in:
parent
37c86f3c15
commit
00425dbe80
@ -88,7 +88,7 @@ class PlayableFolderActivity : AppCompatActivity() {
|
|||||||
browser.shuffleModeEnabled = true
|
browser.shuffleModeEnabled = true
|
||||||
browser.prepare()
|
browser.prepare()
|
||||||
browser.play()
|
browser.play()
|
||||||
browser?.sessionActivity?.send()
|
browser.sessionActivity?.send()
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById<Button>(R.id.play_button).setOnClickListener {
|
findViewById<Button>(R.id.play_button).setOnClickListener {
|
||||||
|
@ -25,6 +25,7 @@ import androidx.media3.session.CommandButton
|
|||||||
import androidx.media3.session.LibraryResult
|
import androidx.media3.session.LibraryResult
|
||||||
import androidx.media3.session.MediaLibraryService
|
import androidx.media3.session.MediaLibraryService
|
||||||
import androidx.media3.session.MediaSession
|
import androidx.media3.session.MediaSession
|
||||||
|
import androidx.media3.session.MediaSession.MediaItemsWithStartPosition
|
||||||
import androidx.media3.session.SessionCommand
|
import androidx.media3.session.SessionCommand
|
||||||
import androidx.media3.session.SessionResult
|
import androidx.media3.session.SessionResult
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
@ -32,7 +33,7 @@ import com.google.common.util.concurrent.Futures
|
|||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
|
||||||
/** A [MediaLibraryService.MediaLibrarySession.Callback] implementation. */
|
/** A [MediaLibraryService.MediaLibrarySession.Callback] implementation. */
|
||||||
open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
open class DemoMediaLibrarySessionCallback(context: Context) :
|
||||||
MediaLibraryService.MediaLibrarySession.Callback {
|
MediaLibraryService.MediaLibrarySession.Callback {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -155,14 +156,7 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
|||||||
controller: MediaSession.ControllerInfo,
|
controller: MediaSession.ControllerInfo,
|
||||||
mediaItems: List<MediaItem>
|
mediaItems: List<MediaItem>
|
||||||
): ListenableFuture<List<MediaItem>> {
|
): ListenableFuture<List<MediaItem>> {
|
||||||
val playlist = mutableListOf<MediaItem>()
|
return Futures.immediateFuture(resolveMediaItems(mediaItems))
|
||||||
mediaItems.forEach { mediaItem ->
|
|
||||||
when (mediaItem.requestMetadata.searchQuery) {
|
|
||||||
null -> MediaItemTree.getItem(mediaItem.mediaId)?.let { playlist.add(it) }
|
|
||||||
else -> playlist.addAll(MediaItemTree.search(mediaItem.requestMetadata.searchQuery!!))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Futures.immediateFuture(playlist)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
|
@OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
|
||||||
@ -172,34 +166,57 @@ open class DemoMediaLibrarySessionCallback(private val context: Context) :
|
|||||||
mediaItems: List<MediaItem>,
|
mediaItems: List<MediaItem>,
|
||||||
startIndex: Int,
|
startIndex: Int,
|
||||||
startPositionMs: Long
|
startPositionMs: Long
|
||||||
): ListenableFuture<MediaSession.MediaItemsWithStartPosition> {
|
): ListenableFuture<MediaItemsWithStartPosition> {
|
||||||
if (mediaItems.size == 1) {
|
if (mediaItems.size == 1) {
|
||||||
// Try to expand a single item to a playlist.
|
// Try to expand a single item to a playlist.
|
||||||
val mediaId = mediaItems.first().mediaId
|
maybeExpandSingleItemToPlaylist(mediaItems.first(), startIndex, startPositionMs)?.also {
|
||||||
val mediaItem = MediaItemTree.getItem(mediaId)
|
return Futures.immediateFuture(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Futures.immediateFuture(
|
||||||
|
MediaItemsWithStartPosition(resolveMediaItems(mediaItems), startIndex, startPositionMs)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveMediaItems(mediaItems: List<MediaItem>): List<MediaItem> {
|
||||||
val playlist = mutableListOf<MediaItem>()
|
val playlist = mutableListOf<MediaItem>()
|
||||||
|
mediaItems.forEach { mediaItem ->
|
||||||
|
if (mediaItem.mediaId.isNotEmpty()) {
|
||||||
|
MediaItemTree.expandItem(mediaItem)?.let { playlist.add(it) }
|
||||||
|
} else if (mediaItem.requestMetadata.searchQuery != null) {
|
||||||
|
playlist.addAll(MediaItemTree.search(mediaItem.requestMetadata.searchQuery!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return playlist
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(UnstableApi::class) // MediaSession.MediaItemsWithStartPosition
|
||||||
|
private fun maybeExpandSingleItemToPlaylist(
|
||||||
|
mediaItem: MediaItem,
|
||||||
|
startIndex: Int,
|
||||||
|
startPositionMs: Long
|
||||||
|
): MediaItemsWithStartPosition? {
|
||||||
|
var playlist = listOf<MediaItem>()
|
||||||
var indexInPlaylist = startIndex
|
var indexInPlaylist = startIndex
|
||||||
mediaItem?.apply {
|
MediaItemTree.getItem(mediaItem.mediaId)?.apply {
|
||||||
if (mediaMetadata.isBrowsable == true) {
|
if (mediaMetadata.isBrowsable == true) {
|
||||||
// Get children browsable item.
|
// Get children browsable item.
|
||||||
playlist.addAll(MediaItemTree.getChildren(mediaId))
|
playlist = MediaItemTree.getChildren(mediaId)
|
||||||
} else if (requestMetadata.searchQuery == null) {
|
} else if (requestMetadata.searchQuery == null) {
|
||||||
// Try to get the parent and its children.
|
// Try to get the parent and its children.
|
||||||
MediaItemTree.getParentId(mediaId)?.let {
|
MediaItemTree.getParentId(mediaId)?.let {
|
||||||
playlist.addAll(MediaItemTree.getChildren(it))
|
playlist =
|
||||||
|
MediaItemTree.getChildren(it).map { mediaItem ->
|
||||||
|
if (mediaItem.mediaId == mediaId) MediaItemTree.expandItem(mediaItem)!! else mediaItem
|
||||||
|
}
|
||||||
indexInPlaylist = MediaItemTree.getIndexInMediaItems(mediaId, playlist)
|
indexInPlaylist = MediaItemTree.getIndexInMediaItems(mediaId, playlist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (playlist.isNotEmpty()) {
|
if (playlist.isNotEmpty()) {
|
||||||
// Return the expanded playlist to be set on the player of the session.
|
return MediaItemsWithStartPosition(playlist, indexInPlaylist, startPositionMs)
|
||||||
return Futures.immediateFuture(
|
|
||||||
MediaSession.MediaItemsWithStartPosition(playlist, indexInPlaylist, startPositionMs)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
return null
|
||||||
// Let super serve the request if item isn't expanded.
|
|
||||||
return super.onSetMediaItems(mediaSession, browser, mediaItems, startIndex, startPositionMs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSearch(
|
override fun onSearch(
|
||||||
|
@ -17,9 +17,11 @@ package androidx.media3.demo.session
|
|||||||
|
|
||||||
import android.content.res.AssetManager
|
import android.content.res.AssetManager
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.annotation.OptIn
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
import androidx.media3.common.MediaItem.SubtitleConfiguration
|
||||||
import androidx.media3.common.MediaMetadata
|
import androidx.media3.common.MediaMetadata
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.lang.StringBuilder
|
import java.lang.StringBuilder
|
||||||
@ -275,6 +277,18 @@ object MediaItemTree {
|
|||||||
return treeNodes[id]?.item
|
return treeNodes[id]?.item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun expandItem(item: MediaItem): MediaItem? {
|
||||||
|
val treeItem = getItem(item.mediaId) ?: return null
|
||||||
|
@OptIn(UnstableApi::class) // MediaMetadata.populate
|
||||||
|
val metadata = treeItem.mediaMetadata.buildUpon().populate(item.mediaMetadata).build()
|
||||||
|
return item
|
||||||
|
.buildUpon()
|
||||||
|
.setMediaMetadata(metadata)
|
||||||
|
.setSubtitleConfigurations(treeItem.localConfiguration?.subtitleConfigurations ?: listOf())
|
||||||
|
.setUri(treeItem.localConfiguration?.uri)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the media ID of the parent of the given media ID, or null if the media ID wasn't found.
|
* Returns the media ID of the parent of the given media ID, or null if the media ID wasn't found.
|
||||||
*
|
*
|
||||||
@ -342,19 +356,6 @@ object MediaItemTree {
|
|||||||
return treeNodes[id]?.getChildren() ?: listOf()
|
return treeNodes[id]?.getChildren() ?: listOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRandomItem(): MediaItem {
|
|
||||||
var curRoot = getRootItem()
|
|
||||||
while (curRoot.mediaMetadata.isBrowsable == true) {
|
|
||||||
val children = getChildren(curRoot.mediaId)
|
|
||||||
curRoot = children.random()
|
|
||||||
}
|
|
||||||
return curRoot
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getItemFromTitle(title: String): MediaItem? {
|
|
||||||
return titleMap[title]?.item
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun normalizeSearchText(text: CharSequence?): String {
|
private fun normalizeSearchText(text: CharSequence?): String {
|
||||||
if (text.isNullOrEmpty() || text.trim().length == 1) {
|
if (text.isNullOrEmpty() || text.trim().length == 1) {
|
||||||
return ""
|
return ""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user