From 545b65921ea4c9f0aff6b344b85a84b4d7e28b66 Mon Sep 17 00:00:00 2001 From: Maxence G Date: Sun, 19 Jun 2022 19:43:55 +0200 Subject: [PATCH] Put Previous/Play/Next in compact notification --- .../playback/MediaNotificationProvider.kt | 153 +++--------------- .../ultrasonic/playback/PlaybackService.kt | 3 +- .../service/MediaPlayerController.kt | 1 - 3 files changed, 24 insertions(+), 133 deletions(-) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/MediaNotificationProvider.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/MediaNotificationProvider.kt index 2bc6e2c8..2aabdc45 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/MediaNotificationProvider.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/MediaNotificationProvider.kt @@ -7,149 +7,42 @@ package org.moire.ultrasonic.playback -/* -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager import android.content.Context -import android.graphics.BitmapFactory -import android.os.Build -import android.os.Bundle import androidx.core.app.NotificationCompat -import androidx.core.graphics.drawable.IconCompat import androidx.media3.common.Player -import androidx.media3.common.util.Assertions import androidx.media3.common.util.UnstableApi -import androidx.media3.common.util.Util +import androidx.media3.common.util.Util.getAvailableCommands +import androidx.media3.session.CommandButton +import androidx.media3.session.DefaultMediaNotificationProvider import androidx.media3.session.MediaController import androidx.media3.session.MediaNotification -import androidx.media3.session.MediaNotification.ActionFactory -import org.moire.ultrasonic.R -*/ +import androidx.media3.session.MediaSession -/* -* This is a copy of DefaultMediaNotificationProvider.java with some small changes -* I have opened a bug https://github.com/androidx/media/issues/65 to make it easier to customize -* the icons and actions without creating our own copy of this class.. - */ -//@UnstableApi -/* package */ -// Disabled while getting updated -/* -internal class MediaNotificationProvider(context: Context) : - MediaNotification.Provider { - private val context: Context = context.applicationContext - private val notificationManager: NotificationManager = Assertions.checkStateNotNull( - context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - ) - @Suppress("LongMethod") - override fun createNotification( - mediaController: MediaController, - actionFactory: ActionFactory, - onNotificationChangedCallback: MediaNotification.Provider.Callback - ): MediaNotification { - ensureNotificationChannel() - val builder: NotificationCompat.Builder = NotificationCompat.Builder( - context, - NOTIFICATION_CHANNEL_ID - ) - // Skip to previous action. - builder.addAction( - actionFactory.createMediaAction( - IconCompat.createWithResource( - context, - R.drawable.media3_notification_seek_to_previous - ), - context.getString(R.string.media3_controls_seek_to_previous_description), - ActionFactory.COMMAND_SKIP_TO_PREVIOUS - ) - ) - if (mediaController.playbackState == Player.STATE_ENDED || - !mediaController.playWhenReady - ) { - // Play action. - builder.addAction( - actionFactory.createMediaAction( - IconCompat.createWithResource(context, R.drawable.media3_notification_play), - context.getString(R.string.media3_controls_play_description), - ActionFactory.COMMAND_PLAY - ) - ) - } else { - // Pause action. - builder.addAction( - actionFactory.createMediaAction( - IconCompat.createWithResource(context, R.drawable.media3_notification_pause), - context.getString(R.string.media3_controls_pause_description), - ActionFactory.COMMAND_PAUSE - ) - ) - } - // Skip to next action. - builder.addAction( - actionFactory.createMediaAction( - IconCompat.createWithResource(context, R.drawable.media3_notification_seek_to_next), - context.getString(R.string.media3_controls_seek_to_next_description), - ActionFactory.COMMAND_SKIP_TO_NEXT - ) - ) +@UnstableApi +class MediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) { - // Set metadata info in the notification. - val metadata = mediaController.mediaMetadata - builder.setContentTitle(metadata.title).setContentText(metadata.artist) - if (metadata.artworkData != null) { - val artworkBitmap = - BitmapFactory.decodeByteArray(metadata.artworkData, 0, metadata.artworkData!!.size) - builder.setLargeIcon(artworkBitmap) - } - val mediaStyle = androidx.media.app.NotificationCompat.MediaStyle() - .setShowActionsInCompactView(0, 1, 2) - val notification: Notification = builder - .setContentIntent(mediaController.sessionActivity) - .setOnlyAlertOnce(true) - .setSmallIcon(getSmallIconResId()) - .setStyle(mediaStyle) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setOngoing(false) - .build() - return MediaNotification( - NOTIFICATION_ID, - notification - ) + override fun addNotificationActions( + mediaSession: MediaSession, + mediaButtons: MutableList, + builder: NotificationCompat.Builder, + actionFactory: MediaNotification.ActionFactory + ): IntArray { + return super.addNotificationActions(mediaSession, mediaButtons, builder, actionFactory) } - override fun handleCustomAction( - mediaController: MediaController, - action: String, - extras: Bundle - ) { - // We don't handle custom commands. - } + override fun getMediaButtons( + playerCommands: Player.Commands, + customLayout: MutableList, + playWhenReady: Boolean + ): MutableList { + val commands = super.getMediaButtons(playerCommands, customLayout, playWhenReady) - private fun ensureNotificationChannel() { - if (Util.SDK_INT < Build.VERSION_CODES.O || - notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) != null - ) { - return + commands.forEachIndexed { index, command -> + command.extras.putInt(COMMAND_KEY_COMPACT_VIEW_INDEX, index) } - val channel = NotificationChannel( - NOTIFICATION_CHANNEL_ID, - NOTIFICATION_CHANNEL_NAME, - NotificationManager.IMPORTANCE_LOW - ) - channel.setShowBadge(false) - notificationManager.createNotificationChannel(channel) - } - - companion object { - private const val NOTIFICATION_CHANNEL_ID = "org.moire.ultrasonic" - private const val NOTIFICATION_CHANNEL_NAME = "Ultrasonic background service" - private const val NOTIFICATION_ID = 3032 - private fun getSmallIconResId(): Int { - return R.drawable.ic_stat_ultrasonic - } + return commands } } -*/ + diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt index 7fee1310..1cdde030 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/playback/PlaybackService.kt @@ -17,7 +17,6 @@ import androidx.media3.datasource.DataSource import androidx.media3.exoplayer.DefaultRenderersFactory import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.source.DefaultMediaSourceFactory -import androidx.media3.session.DefaultMediaNotificationProvider import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaSession import io.reactivex.rxjava3.disposables.CompositeDisposable @@ -90,7 +89,7 @@ class PlaybackService : MediaLibraryService(), KoinComponent { private fun initializeSessionAndPlayer() { if (isStarted) return - setMediaNotificationProvider(DefaultMediaNotificationProvider(UApp.applicationContext())) + setMediaNotificationProvider(MediaNotificationProvider(UApp.applicationContext())) val subsonicAPIClient: SubsonicAPIClient by inject() diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt index 72003cfd..73a5ef25 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/service/MediaPlayerController.kt @@ -659,7 +659,6 @@ fun Track.toMediaItem(): MediaItem { val bitrate = Settings.maxBitRate val uri = "$id|$bitrate|$filePath" - val rmd = MediaItem.RequestMetadata.Builder() .setMediaUri(uri.toUri()) .build()