Skip to content

Commit

Permalink
Trying to fix the mediaplayer notification issues
Browse files Browse the repository at this point in the history
Signed-off-by: Gabriel Fontán <gabilessto@gmail.com>
  • Loading branch information
BobbyESP committed May 15, 2024
1 parent 4c9e44d commit 933b9b7
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ object MediaPlayerModule {
@Singleton
fun provideMediaSessionLayoutHandler(
@ApplicationContext context: Context,
mediaLibrarySessionCallback: MediaLibrarySessionCallback,
mediaLibrarySession: MediaLibrarySession
): MediaSessionLayoutHandler =
MediaSessionLayoutHandlerImpl(context, mediaLibrarySession, mediaLibrarySessionCallback)
MediaSessionLayoutHandlerImpl(context, mediaLibrarySession)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.bobbyesp.mediaplayer.service.notifications

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.media3.ui.PlayerNotificationManager.CustomActionReceiver
import com.bobbyesp.mediaplayer.R

@UnstableApi
class MediaCustomActionReceiver : CustomActionReceiver {
companion object {
const val CUSTOM_ACTION_SHUFFLE =
"com.bobbyesp.mediaplayer.service.notifications.ACTION_SHUFFLE"
const val CUSTOM_ACTION_REPEAT =
"com.bobbyesp.mediaplayer.service.notifications.ACTION_REPEAT"
}

override fun createCustomActions(
context: Context,
instanceId: Int
): MutableMap<String, NotificationCompat.Action> {
val shuffleAction = NotificationCompat.Action.Builder(
R.drawable.shuffle,
context.getString(R.string.action_shuffle_on),
PendingIntent.getBroadcast(
context,
instanceId,
Intent(CUSTOM_ACTION_SHUFFLE).setPackage(context.packageName),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
).build()

val repeatAction = NotificationCompat.Action.Builder(
R.drawable.repeat,
context.getString(R.string.repeat_mode_all),
PendingIntent.getBroadcast(
context,
instanceId,
Intent(CUSTOM_ACTION_REPEAT).setPackage(context.packageName),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
).build()

return mutableMapOf(
CUSTOM_ACTION_SHUFFLE to shuffleAction,
CUSTOM_ACTION_REPEAT to repeatAction
)
}

override fun getCustomActions(player: Player): MutableList<String> {
return mutableListOf(CUSTOM_ACTION_SHUFFLE, CUSTOM_ACTION_REPEAT)
}

override fun onCustomAction(player: Player, action: String, intent: Intent) {
when (action) {
CUSTOM_ACTION_SHUFFLE -> player.shuffleModeEnabled = !player.shuffleModeEnabled
CUSTOM_ACTION_REPEAT -> {
when (player.repeatMode) {
Player.REPEAT_MODE_OFF -> player.repeatMode = Player.REPEAT_MODE_ALL
Player.REPEAT_MODE_ALL -> player.repeatMode = Player.REPEAT_MODE_ONE
Player.REPEAT_MODE_ONE -> player.repeatMode = Player.REPEAT_MODE_OFF
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class MediaNotificationAdapter(
private val context: Context,
private val pendingIntent: PendingIntent?
) : PlayerNotificationManager.MediaDescriptionAdapter {

override fun getCurrentContentTitle(player: Player): CharSequence {
return player.mediaMetadata.albumTitle
?: context.getString(androidx.media3.ui.R.string.exo_track_unknown)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import android.app.NotificationManager
import android.content.Context
import android.os.Build
import android.util.Log
import androidx.annotation.OptIn
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.media3.common.util.UnstableApi
import androidx.media3.common.util.Util
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.session.MediaSession
import androidx.media3.session.MediaSessionService
Expand All @@ -16,16 +19,42 @@ import com.bobbyesp.mediaplayer.R
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject

class MediaNotificationManager @Inject constructor(
@UnstableApi
class MediaNotificationManager @OptIn(UnstableApi::class)
@Inject constructor(
@ApplicationContext private val context: Context,
private val player: ExoPlayer
) {
private val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

val notificationManagerCompat = NotificationManagerCompat.from(context)

init {
Log.i("MediaNotificationManager", "init: creating notification manager")
createNotificationChannel()
ensureNotificationChannel(notificationManagerCompat)
}

val notificationListener = object : PlayerNotificationManager.NotificationListener {
override fun onNotificationCancelled(
notificationId: Int,
dismissedByUser: Boolean
) {
Log.d(
"MediaNotificationManager",
"onNotificationCancelled: notification cancelled"
)
}

override fun onNotificationPosted(
notificationId: Int,
notification: Notification,
ongoing: Boolean
) {
Log.d(
"MediaNotificationManager",
"onNotificationPosted: notification posted"
)
}
}

@UnstableApi
Expand All @@ -46,35 +75,15 @@ class MediaNotificationManager @Inject constructor(
pendingIntent = mediaSession.sessionActivity
)
)
.setCustomActionReceiver(MediaCustomActionReceiver())
.setSmallIconResourceId(R.drawable.metadator_logo_player)
.setNotificationListener(object : PlayerNotificationManager.NotificationListener {
override fun onNotificationCancelled(
notificationId: Int,
dismissedByUser: Boolean
) {
Log.d(
"MediaNotificationManager",
"onNotificationCancelled: notification cancelled"
)
}

override fun onNotificationPosted(
notificationId: Int,
notification: Notification,
ongoing: Boolean
) {
Log.d(
"MediaNotificationManager",
"onNotificationPosted: notification posted"
)
}
})
.setNotificationListener(notificationListener)
.build()
.also { playerNotificationManager ->
with(playerNotificationManager) {
.also {
with(it) {
setMediaSessionToken(mediaSession.sessionCompatToken)
setPriority(NotificationCompat.PRIORITY_LOW)
setPlayer(player)
setPlayer(mediaSession.player)
}
}
}
Expand Down Expand Up @@ -103,15 +112,21 @@ class MediaNotificationManager @Inject constructor(
}
}

private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_LOW
)
notificationManager.createNotificationChannel(channel)
@OptIn(UnstableApi::class)
private fun ensureNotificationChannel(notificationManagerCompat: NotificationManagerCompat) {
if (Util.SDK_INT < 26 || notificationManagerCompat.getNotificationChannel(
NOTIFICATION_CHANNEL_ID
) != null
) {
return
}

val channel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManagerCompat.createNotificationChannel(channel)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.media3.common.Player.REPEAT_MODE_ONE
import androidx.media3.session.CommandButton
import androidx.media3.session.MediaLibraryService
import com.bobbyesp.mediaplayer.R
import com.bobbyesp.mediaplayer.service.MediaLibrarySessionCallback
import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleRepeatMode
import com.bobbyesp.mediaplayer.service.MediaSessionConstants.CommandToggleShuffle
import com.google.common.collect.ImmutableList
Expand All @@ -18,41 +17,40 @@ import javax.inject.Inject
class MediaSessionLayoutHandlerImpl @Inject constructor(
@ApplicationContext private val context: Context,
private val mediaSession: MediaLibraryService.MediaLibrarySession,
private val mediaSessionCallback: MediaLibrarySessionCallback
) : MediaSessionLayoutHandler {

val commandButtons = ImmutableList.of<CommandButton>(
CommandButton.Builder()
.setDisplayName(
getString(
context,
if (mediaSession.player.shuffleModeEnabled) R.string.action_shuffle_on else R.string.action_shuffle_off
override fun updateNotificationLayout() {
val commandButtons = ImmutableList.of<CommandButton>(
CommandButton.Builder()
.setDisplayName(
getString(
context,
if (mediaSession.player.shuffleModeEnabled) R.string.action_shuffle_on else R.string.action_shuffle_off
)
)
)
.setIconResId(if (mediaSession.player.shuffleModeEnabled) R.drawable.shuffle_on else R.drawable.shuffle)
.setSessionCommand(CommandToggleShuffle).build(),
CommandButton.Builder()
.setDisplayName(
getString(
context,
.setIconResId(if (mediaSession.player.shuffleModeEnabled) R.drawable.shuffle_on else R.drawable.shuffle)
.setSessionCommand(CommandToggleShuffle).build(),
CommandButton.Builder()
.setDisplayName(
getString(
context,
when (mediaSession.player.repeatMode) {
REPEAT_MODE_OFF -> R.string.repeat_mode_off
REPEAT_MODE_ONE -> R.string.repeat_mode_one
REPEAT_MODE_ALL -> R.string.repeat_mode_all
else -> throw IllegalStateException()
}
)
).setIconResId(
when (mediaSession.player.repeatMode) {
REPEAT_MODE_OFF -> R.string.repeat_mode_off
REPEAT_MODE_ONE -> R.string.repeat_mode_one
REPEAT_MODE_ALL -> R.string.repeat_mode_all
REPEAT_MODE_OFF -> R.drawable.repeat
REPEAT_MODE_ONE -> R.drawable.repeat_one_on
REPEAT_MODE_ALL -> R.drawable.repeat_on
else -> throw IllegalStateException()
}
)
).setIconResId(
when (mediaSession.player.repeatMode) {
REPEAT_MODE_OFF -> R.drawable.repeat
REPEAT_MODE_ONE -> R.drawable.repeat_one_on
REPEAT_MODE_ALL -> R.drawable.repeat_on
else -> throw IllegalStateException()
}
).setSessionCommand(CommandToggleRepeatMode).build()
)
).setSessionCommand(CommandToggleRepeatMode).build()
)

override fun updateNotificationLayout() {
mediaSession.setCustomLayout(commandButtons)
}
}

0 comments on commit 933b9b7

Please sign in to comment.