Put Previous/Play/Next in compact notification

This commit is contained in:
Maxence G 2022-06-19 19:43:55 +02:00
parent cf367ead92
commit 545b65921e
No known key found for this signature in database
GPG Key ID: DC1FD9409E3FE284
3 changed files with 24 additions and 133 deletions

View File

@ -7,149 +7,42 @@
package org.moire.ultrasonic.playback package org.moire.ultrasonic.playback
/*
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Bundle
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.common.util.Assertions
import androidx.media3.common.util.UnstableApi 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.MediaController
import androidx.media3.session.MediaNotification import androidx.media3.session.MediaNotification
import androidx.media3.session.MediaNotification.ActionFactory import androidx.media3.session.MediaSession
import org.moire.ultrasonic.R
*/
/*
* 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") @UnstableApi
override fun createNotification( class MediaNotificationProvider(context: Context) : DefaultMediaNotificationProvider(context) {
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
)
)
// Set metadata info in the notification. override fun addNotificationActions(
val metadata = mediaController.mediaMetadata mediaSession: MediaSession,
builder.setContentTitle(metadata.title).setContentText(metadata.artist) mediaButtons: MutableList<CommandButton>,
if (metadata.artworkData != null) { builder: NotificationCompat.Builder,
val artworkBitmap = actionFactory: MediaNotification.ActionFactory
BitmapFactory.decodeByteArray(metadata.artworkData, 0, metadata.artworkData!!.size) ): IntArray {
builder.setLargeIcon(artworkBitmap) return super.addNotificationActions(mediaSession, mediaButtons, builder, actionFactory)
}
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 handleCustomAction( override fun getMediaButtons(
mediaController: MediaController, playerCommands: Player.Commands,
action: String, customLayout: MutableList<CommandButton>,
extras: Bundle playWhenReady: Boolean
) { ): MutableList<CommandButton> {
// We don't handle custom commands. val commands = super.getMediaButtons(playerCommands, customLayout, playWhenReady)
commands.forEachIndexed { index, command ->
command.extras.putInt(COMMAND_KEY_COMPACT_VIEW_INDEX, index)
} }
private fun ensureNotificationChannel() { return commands
if (Util.SDK_INT < Build.VERSION_CODES.O ||
notificationManager.getNotificationChannel(NOTIFICATION_CHANNEL_ID) != null
) {
return
} }
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
}
}
}
*/

View File

@ -17,7 +17,6 @@ import androidx.media3.datasource.DataSource
import androidx.media3.exoplayer.DefaultRenderersFactory import androidx.media3.exoplayer.DefaultRenderersFactory
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.DefaultMediaNotificationProvider
import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaLibraryService
import androidx.media3.session.MediaSession import androidx.media3.session.MediaSession
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
@ -90,7 +89,7 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
private fun initializeSessionAndPlayer() { private fun initializeSessionAndPlayer() {
if (isStarted) return if (isStarted) return
setMediaNotificationProvider(DefaultMediaNotificationProvider(UApp.applicationContext())) setMediaNotificationProvider(MediaNotificationProvider(UApp.applicationContext()))
val subsonicAPIClient: SubsonicAPIClient by inject() val subsonicAPIClient: SubsonicAPIClient by inject()

View File

@ -659,7 +659,6 @@ fun Track.toMediaItem(): MediaItem {
val bitrate = Settings.maxBitRate val bitrate = Settings.maxBitRate
val uri = "$id|$bitrate|$filePath" val uri = "$id|$bitrate|$filePath"
val rmd = MediaItem.RequestMetadata.Builder() val rmd = MediaItem.RequestMetadata.Builder()
.setMediaUri(uri.toUri()) .setMediaUri(uri.toUri())
.build() .build()