Cache notification thumbnails

This commit is contained in:
vfsfitvnm 2022-06-14 16:49:11 +02:00
parent 9d1e52083c
commit cb8e4c41d1

View file

@ -35,11 +35,12 @@ import androidx.media3.exoplayer.analytics.PlaybackStatsListener
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.session.* import androidx.media3.session.*
import androidx.media3.session.MediaNotification.ActionFactory import androidx.media3.session.MediaNotification.ActionFactory
import coil.ImageLoader import coil.Coil
import coil.request.ImageRequest import coil.request.ImageRequest
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import it.vfsfitvnm.vimusic.* import it.vfsfitvnm.vimusic.Database
import it.vfsfitvnm.vimusic.MainActivity
import it.vfsfitvnm.vimusic.R import it.vfsfitvnm.vimusic.R
import it.vfsfitvnm.vimusic.utils.* import it.vfsfitvnm.vimusic.utils.*
import it.vfsfitvnm.youtubemusic.Outcome import it.vfsfitvnm.youtubemusic.Outcome
@ -79,6 +80,7 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
private lateinit var notificationManager: NotificationManager private lateinit var notificationManager: NotificationManager
private var notificationThumbnailSize: Int = 0
private var lastArtworkUri: Uri? = null private var lastArtworkUri: Uri? = null
private var lastBitmap: Bitmap? = null private var lastBitmap: Bitmap? = null
@ -89,6 +91,8 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
notificationThumbnailSize = (96 * resources.displayMetrics.density).roundToInt()
createNotificationChannel() createNotificationChannel()
setMediaNotificationProvider(this) setMediaNotificationProvider(this)
@ -178,7 +182,12 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
} }
StopRadioCommand -> radio = null StopRadioCommand -> radio = null
GetCacheSizeCommand -> { GetCacheSizeCommand -> {
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS, bundleOf("cacheSize" to cache.cacheSpace))) return Futures.immediateFuture(
SessionResult(
SessionResult.RESULT_SUCCESS,
bundleOf("cacheSize" to cache.cacheSpace)
)
)
} }
DeleteSongCacheCommand -> { DeleteSongCacheCommand -> {
args.getString("videoId")?.let { videoId -> args.getString("videoId")?.let { videoId ->
@ -189,7 +198,12 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
player.skipSilenceEnabled = args.getBoolean("skipSilence") player.skipSilenceEnabled = args.getBoolean("skipSilence")
} }
GetAudioSessionIdCommand -> { GetAudioSessionIdCommand -> {
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS, bundleOf("audioSessionId" to player.audioSessionId))) return Futures.immediateFuture(
SessionResult(
SessionResult.RESULT_SUCCESS,
bundleOf("audioSessionId" to player.audioSessionId)
)
)
} }
} }
@ -235,6 +249,16 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
actionFactory: ActionFactory, actionFactory: ActionFactory,
onNotificationChangedCallback: MediaNotification.Provider.Callback onNotificationChangedCallback: MediaNotification.Provider.Callback
): MediaNotification { ): MediaNotification {
fun invalidate() {
onNotificationChangedCallback.onNotificationChanged(
createNotification(
mediaController,
actionFactory,
onNotificationChangedCallback
)
)
}
fun NotificationCompat.Builder.addMediaAction( fun NotificationCompat.Builder.addMediaAction(
@DrawableRes resId: Int, @DrawableRes resId: Int,
@StringRes stringId: Int, @StringRes stringId: Int,
@ -254,6 +278,20 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
val builder = NotificationCompat.Builder(applicationContext, NotificationChannelId) val builder = NotificationCompat.Builder(applicationContext, NotificationChannelId)
.setContentTitle(mediaMetadata.title) .setContentTitle(mediaMetadata.title)
.setContentText(mediaMetadata.artist) .setContentText(mediaMetadata.artist)
.setLargeIcon(lastBitmap)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setShowWhen(false)
.setSmallIcon(R.drawable.app_icon)
.setOngoing(false)
.setContentIntent(mediaController.sessionActivity)
.setDeleteIntent(actionFactory.createMediaActionPendingIntent(ActionFactory.COMMAND_STOP))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mediaSession.sessionCompatToken as android.support.v4.media.session.MediaSessionCompat.Token)
)
.addMediaAction( .addMediaAction(
R.drawable.play_skip_back, R.drawable.play_skip_back,
R.string.media3_controls_seek_to_previous_description, R.string.media3_controls_seek_to_previous_description,
@ -277,51 +315,23 @@ class PlayerService : MediaSessionService(), MediaSession.MediaItemFiller,
R.string.media3_controls_seek_to_next_description, R.string.media3_controls_seek_to_next_description,
ActionFactory.COMMAND_SKIP_TO_NEXT ActionFactory.COMMAND_SKIP_TO_NEXT
) )
.setContentIntent(mediaController.sessionActivity)
.setDeleteIntent(
actionFactory.createMediaActionPendingIntent(
ActionFactory.COMMAND_STOP
)
)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
.setShowWhen(false)
.setSmallIcon(R.drawable.app_icon)
.setOngoing(false)
.setStyle(
androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mediaSession.sessionCompatToken as android.support.v4.media.session.MediaSessionCompat.Token)
)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (lastArtworkUri != mediaMetadata.artworkUri) {
if (lastArtworkUri == mediaMetadata.artworkUri) { coroutineScope.launch(Dispatchers.IO) {
builder.setLargeIcon(lastBitmap) lastBitmap = Coil.imageLoader(applicationContext).execute(
} else {
val size = (96 * resources.displayMetrics.density).roundToInt()
builder.setLargeIcon(
resources.getDrawable(R.drawable.disc_placeholder, null)?.toBitmap(size, size)
)
ImageLoader(applicationContext)
.enqueue(
ImageRequest.Builder(applicationContext) ImageRequest.Builder(applicationContext)
.listener { _, result -> .data("${mediaMetadata.artworkUri}-w${notificationThumbnailSize}-h${notificationThumbnailSize}")
lastBitmap = (result.drawable as BitmapDrawable).bitmap
lastArtworkUri = mediaMetadata.artworkUri
onNotificationChangedCallback.onNotificationChanged(
MediaNotification(
NotificationId,
builder.setLargeIcon(lastBitmap).build()
)
)
}
.data("${mediaMetadata.artworkUri}-w${size}-h${size}")
.build() .build()
) ).drawable?.let {
lastArtworkUri = mediaMetadata.artworkUri
(it as BitmapDrawable).bitmap
} ?: resources.getDrawable(R.drawable.disc_placeholder, null)
?.toBitmap(notificationThumbnailSize, notificationThumbnailSize)
withContext(Dispatchers.Main) {
invalidate()
}
}
} }
return MediaNotification(NotificationId, builder.build()) return MediaNotification(NotificationId, builder.build())