[Android] Fix the Android auto search results

Nicolas Pomepuy git at videolan.org
Mon Mar 3 10:40:14 UTC 2025


vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Tue Feb 25 08:03:01 2025 +0100| [039d7afb5e0495a1f62c34cdae7911cdd98d0281] | committer: Robert Stone

Fix the Android auto search results

Return playable (not browsable) media items

Show types (Artist, album, etc.) in subtitle instead of group header

> https://code.videolan.org/videolan/vlc-android/commit/039d7afb5e0495a1f62c34cdae7911cdd98d0281
---

 .../resources/src/main/res/values/strings.xml      |  5 ++
 .../org/videolan/vlc/media/MediaSessionBrowser.kt  | 59 +++++++++++++++++-----
 2 files changed, 50 insertions(+), 14 deletions(-)

diff --git a/application/resources/src/main/res/values/strings.xml b/application/resources/src/main/res/values/strings.xml
index 8fb154fb98..3e09701a2c 100644
--- a/application/resources/src/main/res/values/strings.xml
+++ b/application/resources/src/main/res/values/strings.xml
@@ -394,6 +394,11 @@
     <string name="enable_android_auto_speed_buttons_summary">Show speed control in the overflow menu</string>
     <string name="enable_android_auto_seek_buttons">Android Auto seek buttons</string>
     <string name="enable_android_auto_seek_buttons_summary">Show rewind and fast forward in the overflow menu. Try holding steering wheel previous and next buttons before enabling.</string>
+    <string name="artist">Artist</string>
+    <string name="album">Album</string>
+    <string name="track">Track</string>
+    <string name="genre">Genre</string>
+    <string name="playlist">Playlist</string>
     <string name="enable_double_tap_seek_title">Double tap to seek</string>
     <string name="enable_double_tap_seek_summary">Double tap on screen edges to seek by 10 seconds</string>
     <string name="enable_double_tap_play_title">Double tap to play/pause</string>
diff --git a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt
index 62e817da0c..fbb821a6e0 100644
--- a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt
+++ b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt
@@ -39,8 +39,24 @@ import org.videolan.medialibrary.interfaces.media.Album
 import org.videolan.medialibrary.interfaces.media.MediaWrapper
 import org.videolan.medialibrary.interfaces.media.Playlist
 import org.videolan.medialibrary.media.MediaLibraryItem
-import org.videolan.resources.*
-import org.videolan.tools.*
+import org.videolan.resources.CONTENT_STYLE_BROWSABLE_HINT
+import org.videolan.resources.CONTENT_STYLE_CATEGORY_ITEM_HINT_VALUE
+import org.videolan.resources.CONTENT_STYLE_GRID_ITEM_HINT_VALUE
+import org.videolan.resources.CONTENT_STYLE_LIST_ITEM_HINT_VALUE
+import org.videolan.resources.CONTENT_STYLE_PLAYABLE_HINT
+import org.videolan.resources.EXTRA_BROWSER_ICON_SIZE
+import org.videolan.resources.EXTRA_CONTENT_STYLE_GROUP_TITLE_HINT
+import org.videolan.resources.EXTRA_CONTENT_STYLE_SINGLE_ITEM
+import org.videolan.resources.EXTRA_RELATIVE_MEDIA_ID
+import org.videolan.tools.KEY_ARTISTS_SHOW_ALL
+import org.videolan.tools.PLAYBACK_HISTORY
+import org.videolan.tools.Settings
+import org.videolan.tools.abbreviate
+import org.videolan.tools.getResourceUri
+import org.videolan.tools.markBidi
+import org.videolan.tools.removeQuery
+import org.videolan.tools.retrieveParent
+import org.videolan.tools.toInt
 import org.videolan.vlc.ArtworkProvider
 import org.videolan.vlc.BuildConfig
 import org.videolan.vlc.R
@@ -355,7 +371,7 @@ class MediaSessionBrowser {
                     }
                 }
             }
-            results.addAll(buildMediaItems(context, parentId, list, null, limitSize, androidAuto = isAndroidAuto))
+            results.addAll(buildMediaItems(context, parentId, list, limitSize, androidAuto = isAndroidAuto))
             if (results.isEmpty()) {
                 val emptyMediaDesc = MediaDescriptionCompat.Builder()
                         .setMediaId(ID_NO_MEDIA)
@@ -392,11 +408,11 @@ class MediaSessionBrowser {
             val isAndroidAuto = rootHints?.containsKey(EXTRA_BROWSER_ICON_SIZE) ?: false
             val searchAggregate = Medialibrary.getInstance().search(query, false, false)
             val searchMediaId = ID_SEARCH.toUri().buildUpon().appendQueryParameter("query", query).toString()
-            results.addAll(buildMediaItems(context, ID_PLAYLIST, searchAggregate.playlists, res.getString(R.string.playlists)))
-            results.addAll(buildMediaItems(context, ID_GENRE, searchAggregate.genres, res.getString(R.string.genres)))
-            results.addAll(buildMediaItems(context, ID_ARTIST, searchAggregate.artists, res.getString(R.string.artists)))
-            results.addAll(buildMediaItems(context, ID_ALBUM, searchAggregate.albums, res.getString(R.string.albums)))
-            results.addAll(buildMediaItems(context, searchMediaId, searchAggregate.tracks, res.getString(R.string.tracks), androidAuto = isAndroidAuto))
+            results.addAll(buildMediaItems(context, ID_PLAYLIST, searchAggregate.playlists, forSearch = true))
+            results.addAll(buildMediaItems(context, ID_GENRE, searchAggregate.genres, forSearch = true))
+            results.addAll(buildMediaItems(context, ID_ARTIST, searchAggregate.artists, forSearch = true))
+            results.addAll(buildMediaItems(context, ID_ALBUM, searchAggregate.albums, forSearch = true))
+            results.addAll(buildMediaItems(context, searchMediaId, searchAggregate.tracks, androidAuto = isAndroidAuto, forSearch = true))
             if (results.isEmpty()) {
                 val emptyMediaDesc = MediaDescriptionCompat.Builder()
                         .setMediaId(ID_NO_MEDIA)
@@ -436,7 +452,7 @@ class MediaSessionBrowser {
             /* Query albums by name */
             val albums = mutableSetOf<Album>()
             for (albumName in albumNames) ml.searchAlbum(albumName)?.let { albums.addAll(it.toList()) }
-            results.addAll(buildMediaItems(context, parentId, albums.toTypedArray(), null, limitSize = false, suggestionMode = true)
+            results.addAll(buildMediaItems(context, parentId, albums.toTypedArray(), limitSize = false, suggestionMode = true)
                     .take((MAX_SUGGESTED_SIZE - results.size).coerceAtLeast(0)))
             return results
         }
@@ -450,12 +466,12 @@ class MediaSessionBrowser {
          * will pass the argument from the calling application. The search function will use a
          * placeholder value to act as if the user navigated to the location.
          * @param list MediaLibraryItems to process into MediaBrowserCompat.MediaItems
-         * @param groupTitle Common heading to group items (unused if null)
          * @param limitSize Limit the number of items returned (default is false)
          * @return List containing fully constructed MediaBrowser MediaItem
          */
-        private fun buildMediaItems(context: Context, parentId: String, list: Array<out MediaLibraryItem>?, groupTitle: String?,
-                                    limitSize: Boolean = false, suggestionMode: Boolean = false, androidAuto: Boolean = false): List<MediaBrowserCompat.MediaItem> {
+        private fun buildMediaItems(context: Context, parentId: String, list: Array<out MediaLibraryItem>?,
+                                    limitSize: Boolean = false, suggestionMode: Boolean = false,
+                                    androidAuto: Boolean = false, forSearch: Boolean = false): List<MediaBrowserCompat.MediaItem> {
             if (list.isNullOrEmpty()) return emptyList()
             val res = context.resources
             val artworkToUriCache = HashMap<String, Uri>()
@@ -503,13 +519,25 @@ class MediaSessionBrowser {
                     }
                     else -> libraryItem.description
                 }
+                val mediaType = when (libraryItem.itemType) {
+                    MediaLibraryItem.TYPE_MEDIA ->
+                       res.getString(R.string.track)
+                    MediaLibraryItem.TYPE_PLAYLIST ->
+                        res.getString(R.string.playlist)
+                    MediaLibraryItem.TYPE_ARTIST ->
+                        res.getString(R.string.artist)
+                    MediaLibraryItem.TYPE_GENRE ->
+                        res.getString(R.string.genre)
+                    MediaLibraryItem.TYPE_ALBUM ->
+                        res.getString(R.string.album)
+                    else -> ""
+                }
 
                 /* Extras */
                 val extras = when (libraryItem.itemType) {
                     MediaLibraryItem.TYPE_ARTIST, MediaLibraryItem.TYPE_GENRE -> getContentStyle(CONTENT_STYLE_GRID_ITEM_HINT_VALUE, CONTENT_STYLE_GRID_ITEM_HINT_VALUE)
                     else -> Bundle()
                 }
-                if (groupTitle != null) extras.putString(EXTRA_CONTENT_STYLE_GROUP_TITLE_HINT, groupTitle)
 
                 if (libraryItem.itemType == MediaLibraryItem.TYPE_MEDIA && (libraryItem as MediaWrapper).isPodcast) {
                     var pct = libraryItem.position.toDouble()
@@ -586,7 +614,7 @@ class MediaSessionBrowser {
                  */
                 val description = MediaDescriptionCompat.Builder()
                         .setTitle(libraryItem.title)
-                        .setSubtitle(subtitle)
+                        .setSubtitle(if (forSearch) "$mediaType ${TextUtils.SEPARATOR} $subtitle" else subtitle)
                         .setIconUri(iconUri)
                         .setMediaId(mediaId)
                         .setExtras(extras)
@@ -602,6 +630,9 @@ class MediaSessionBrowser {
                     flags = MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
                     if (iconUri == null || iconUri.scheme == ContentResolver.SCHEME_ANDROID_RESOURCE) continue
                 }
+                if (forSearch) {
+                    flags = MediaBrowserCompat.MediaItem.FLAG_PLAYABLE
+                }
                 results.add(MediaBrowserCompat.MediaItem(description, flags))
                 if ((limitSize && results.size == MAX_HISTORY_SIZE) || results.size == MAX_RESULT_SIZE) break
             }



More information about the Android mailing list