Cache notification thumbnails
This commit is contained in:
parent
9d1e52083c
commit
cb8e4c41d1
1 changed files with 56 additions and 46 deletions
|
@ -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())
|
||||||
|
|
Loading…
Add table
Reference in a new issue