Merge pull request 'fix(android): notification art uses album cover, not embedded stream tags' (#84) from dev into main
This commit was merged in pull request #84.
This commit is contained in:
@@ -77,6 +77,7 @@ class MinstrelPlayerService : MediaSessionService() {
|
|||||||
val session = MediaSession.Builder(this, player)
|
val session = MediaSession.Builder(this, player)
|
||||||
.setSessionActivity(buildNowPlayingPendingIntent())
|
.setSessionActivity(buildNowPlayingPendingIntent())
|
||||||
.setCallback(callback)
|
.setCallback(callback)
|
||||||
|
.setBitmapLoader(playerFactory.buildBitmapLoader())
|
||||||
.setMediaButtonPreferences(ImmutableList.of(buildLikeButton(isLiked = false)))
|
.setMediaButtonPreferences(ImmutableList.of(buildLikeButton(isLiked = false)))
|
||||||
.build()
|
.build()
|
||||||
mediaSession = session
|
mediaSession = session
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import android.os.Bundle
|
|||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import androidx.core.net.toUri
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import androidx.media3.common.MediaMetadata
|
import androidx.media3.common.MediaMetadata
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
@@ -671,6 +672,18 @@ class PlayerController @Inject constructor(
|
|||||||
// paused under UPnP (it never probes a duration in that state).
|
// paused under UPnP (it never probes a duration in that state).
|
||||||
if (durationSec > 0) setDurationMs(durationSec.toLong() * MS_PER_SECOND)
|
if (durationSec > 0) setDurationMs(durationSec.toLong() * MS_PER_SECOND)
|
||||||
if (source != null) setExtras(sourceExtras(source))
|
if (source != null) setExtras(sourceExtras(source))
|
||||||
|
// Point the notification / lock-screen art at the SAME album
|
||||||
|
// cover the in-app surfaces use (TrackRef.coverUrl ->
|
||||||
|
// /api/albums/{id}/cover). Without this, Media3 falls back to
|
||||||
|
// whatever art is embedded in the stream's tags, which can be a
|
||||||
|
// different image than the server's album cover. Setting
|
||||||
|
// artworkUri here is load-bearing: MediaMetadata.populate()
|
||||||
|
// overwrites artworkUri + artworkData as a pair, so the
|
||||||
|
// MediaItem's URI clears any embedded artworkData ExoPlayer
|
||||||
|
// extracts from the stream -- the cover endpoint wins on both
|
||||||
|
// surfaces. The session's OkHttp-backed BitmapLoader (see
|
||||||
|
// PlayerFactory) is what makes this authed placeholder URL load.
|
||||||
|
if (coverUrl.isNotEmpty()) setArtworkUri(coverUrl.toUri())
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
// Server's stream_url is a relative path (/api/tracks/{id}/stream);
|
// Server's stream_url is a relative path (/api/tracks/{id}/stream);
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import android.content.Context
|
|||||||
import androidx.media3.common.AudioAttributes
|
import androidx.media3.common.AudioAttributes
|
||||||
import androidx.media3.common.C
|
import androidx.media3.common.C
|
||||||
import androidx.media3.common.Player
|
import androidx.media3.common.Player
|
||||||
|
import androidx.media3.common.util.BitmapLoader
|
||||||
import androidx.media3.database.StandaloneDatabaseProvider
|
import androidx.media3.database.StandaloneDatabaseProvider
|
||||||
|
import androidx.media3.datasource.DataSourceBitmapLoader
|
||||||
import androidx.media3.datasource.cache.CacheDataSink
|
import androidx.media3.datasource.cache.CacheDataSink
|
||||||
import androidx.media3.datasource.cache.CacheDataSource
|
import androidx.media3.datasource.cache.CacheDataSource
|
||||||
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
import androidx.media3.datasource.cache.LeastRecentlyUsedCacheEvictor
|
||||||
@@ -12,6 +14,7 @@ import androidx.media3.datasource.cache.SimpleCache
|
|||||||
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
import androidx.media3.datasource.okhttp.OkHttpDataSource
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
||||||
|
import androidx.media3.session.CacheBitmapLoader
|
||||||
import com.fabledsword.minstrel.cache.audiocache.CacheConfig
|
import com.fabledsword.minstrel.cache.audiocache.CacheConfig
|
||||||
import com.fabledsword.minstrel.player.output.ActiveUpnpHolder
|
import com.fabledsword.minstrel.player.output.ActiveUpnpHolder
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
@@ -113,6 +116,24 @@ class PlayerFactory @Inject constructor(
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BitmapLoader for the MediaSession's notification / lock-screen art.
|
||||||
|
* Backed by the shared [okHttpClient] so it inherits the same
|
||||||
|
* BaseUrlInterceptor placeholder rewrite + auth cookie that Coil uses
|
||||||
|
* for in-app covers — without it the default DefaultHttpDataSource
|
||||||
|
* loader can't resolve `http://placeholder.invalid/...` and would 401
|
||||||
|
* on the cover endpoint. Wrapped in CacheBitmapLoader so a cover the
|
||||||
|
* notification already fetched isn't re-loaded on every metadata
|
||||||
|
* refresh. Lets the album-cover artworkUri set in
|
||||||
|
* [PlayerController.toMediaItem] actually render on the media card.
|
||||||
|
*/
|
||||||
|
fun buildBitmapLoader(): BitmapLoader =
|
||||||
|
CacheBitmapLoader(
|
||||||
|
DataSourceBitmapLoader.Builder(context)
|
||||||
|
.setDataSourceFactory(OkHttpDataSource.Factory(okHttpClient))
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
|
||||||
private fun emitDrop(routeName: String) {
|
private fun emitDrop(routeName: String) {
|
||||||
dropEventsInternal.tryEmit(routeName)
|
dropEventsInternal.tryEmit(routeName)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user