Merge pull request #6857 from Bnyro/master

refactor: use skip/previous buttons from DefaultMediaNotificationProvider
This commit is contained in:
Bnyro 2024-12-05 23:08:14 +01:00 committed by GitHub
commit 848ac85c37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -10,19 +10,18 @@ import androidx.core.app.ServiceCompat
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.os.postDelayed import androidx.core.os.postDelayed
import androidx.media3.common.C import androidx.media3.common.C
import androidx.media3.common.ForwardingPlayer
import androidx.media3.common.MediaMetadata import androidx.media3.common.MediaMetadata
import androidx.media3.common.PlaybackException import androidx.media3.common.PlaybackException
import androidx.media3.common.Player import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector import androidx.media3.exoplayer.trackselection.DefaultTrackSelector
import androidx.media3.session.CommandButton
import androidx.media3.session.MediaLibraryService import androidx.media3.session.MediaLibraryService
import androidx.media3.session.MediaLibraryService.MediaLibrarySession import androidx.media3.session.MediaLibraryService.MediaLibrarySession
import androidx.media3.session.MediaSession import androidx.media3.session.MediaSession
import androidx.media3.session.SessionCommand import androidx.media3.session.SessionCommand
import androidx.media3.session.SessionResult import androidx.media3.session.SessionResult
import com.github.libretube.R
import com.github.libretube.api.obj.Subtitle import com.github.libretube.api.obj.Subtitle
import com.github.libretube.constants.IntentData import com.github.libretube.constants.IntentData
import com.github.libretube.enums.PlayerCommand import com.github.libretube.enums.PlayerCommand
@ -261,19 +260,6 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
): MediaSession.ConnectionResult { ): MediaSession.ConnectionResult {
val connectionResult = super.onConnect(session, controller) val connectionResult = super.onConnect(session, controller)
// Select the button to display.
val customLayout = listOf(
CommandButton.Builder()
.setDisplayName(getString(R.string.rewind))
.setSessionCommand(SessionCommand(PlayerEvent.Prev.name, Bundle.EMPTY))
.setIconResId(R.drawable.ic_prev_outlined)
.build(),
CommandButton.Builder()
.setDisplayName(getString(R.string.play_next))
.setSessionCommand(SessionCommand(PlayerEvent.Next.name, Bundle.EMPTY))
.setIconResId(R.drawable.ic_next_outlined)
.build(),
)
val mediaNotificationSessionCommands = val mediaNotificationSessionCommands =
connectionResult.availableSessionCommands.buildUpon() connectionResult.availableSessionCommands.buildUpon()
.also { builder -> .also { builder ->
@ -284,18 +270,17 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
stopServiceCommand stopServiceCommand
) )
) )
builder.addSessionCommands(customLayout.mapNotNull(CommandButton::sessionCommand))
} }
.build() .build()
val playerCommands = connectionResult.availablePlayerCommands.buildUpon() val playerCommands = connectionResult.availablePlayerCommands.buildUpon()
.remove(Player.COMMAND_SEEK_TO_PREVIOUS) .add(Player.COMMAND_SEEK_TO_NEXT)
.add(Player.COMMAND_SEEK_TO_PREVIOUS)
.build() .build()
return MediaSession.ConnectionResult.AcceptedResultBuilder(session) return MediaSession.ConnectionResult.AcceptedResultBuilder(session)
.setAvailableSessionCommands(mediaNotificationSessionCommands) .setAvailableSessionCommands(mediaNotificationSessionCommands)
.setAvailablePlayerCommands(playerCommands) .setAvailablePlayerCommands(playerCommands)
.setCustomLayout(customLayout)
.build() .build()
} }
@ -318,7 +303,8 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
PlayerHelper.setPreferredCodecs(trackSelector) PlayerHelper.setPreferredCodecs(trackSelector)
mediaLibrarySession = MediaLibrarySession.Builder(this, player, this) val forwardingPlayer = MediaSessionForwarder(player)
mediaLibrarySession = MediaLibrarySession.Builder(this, forwardingPlayer, this)
.setId(this.javaClass.name) .setId(this.javaClass.name)
.build() .build()
} }
@ -347,16 +333,20 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
handlePlayerAction(PlayerEvent.Next) handlePlayerAction(PlayerEvent.Next)
return true return true
} }
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> { KeyEvent.KEYCODE_MEDIA_PREVIOUS -> {
handlePlayerAction(PlayerEvent.Prev) handlePlayerAction(PlayerEvent.Prev)
return true return true
} }
KeyEvent.KEYCODE_MEDIA_REWIND -> { KeyEvent.KEYCODE_MEDIA_REWIND -> {
handlePlayerAction(PlayerEvent.Rewind) handlePlayerAction(PlayerEvent.Rewind)
} }
KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> { KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
handlePlayerAction(PlayerEvent.Forward) handlePlayerAction(PlayerEvent.Forward)
} }
KeyEvent.KEYCODE_MEDIA_STOP -> { KeyEvent.KEYCODE_MEDIA_STOP -> {
handlePlayerAction(PlayerEvent.Stop) handlePlayerAction(PlayerEvent.Stop)
} }
@ -406,6 +396,40 @@ abstract class AbstractPlayerService : MediaLibraryService(), MediaLibrarySessio
onDestroy() onDestroy()
} }
/**
* [Player] wrapper that handles seeking actions (next/previous) itself instead of using the
* default [Player] implementation
*/
inner class MediaSessionForwarder(player: Player) : ForwardingPlayer(player) {
override fun hasNextMediaItem(): Boolean {
return PlayingQueue.hasNext()
}
override fun hasPreviousMediaItem(): Boolean {
return PlayingQueue.hasPrev()
}
override fun seekToPrevious() {
handlePlayerAction(PlayerEvent.Prev)
}
override fun seekToNext() {
handlePlayerAction(PlayerEvent.Next)
}
override fun getAvailableCommands(): Player.Commands {
return super.getAvailableCommands().buildUpon()
.addAll(Player.COMMAND_SEEK_TO_PREVIOUS, Player.COMMAND_SEEK_TO_NEXT)
.build()
}
override fun isCommandAvailable(command: Int): Boolean {
if (command == Player.COMMAND_SEEK_TO_NEXT || command == Player.COMMAND_SEEK_TO_PREVIOUS) return true
return super.isCommandAvailable(command)
}
}
companion object { companion object {
private const val START_SERVICE_ACTION = "start_service_action" private const val START_SERVICE_ACTION = "start_service_action"
private const val STOP_SERVICE_ACTION = "stop_service_action" private const val STOP_SERVICE_ACTION = "stop_service_action"