diff --git a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
index b81c67da..00c05051 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/data/DeviceClasses.kt
@@ -39,7 +39,7 @@ data class DeviceSettings(
@get:JsonIgnore
val jumpBackwardsTimeMs get() = (jumpBackwardsTime ?: default().jumpBackwardsTime) * 1000L
@get:JsonIgnore
- val jumpForwardTimeMs get() = (jumpForwardTime ?: default().jumpBackwardsTime) * 1000L
+ val jumpForwardTimeMs get() = (jumpForwardTime ?: default().jumpForwardTime) * 1000L
}
data class DeviceData(
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
index 63460461..7fbdcadd 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
@@ -239,6 +239,8 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
when (action) {
CUSTOM_ACTION_JUMP_FORWARD -> onFastForward()
CUSTOM_ACTION_JUMP_BACKWARD -> onRewind()
+ CUSTOM_ACTION_SKIP_FORWARD -> onSkipToNext()
+ CUSTOM_ACTION_SKIP_BACKWARD -> onSkipToPrevious()
}
}
}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerConstants.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerConstants.kt
index 407425f8..cbf9f76e 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerConstants.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerConstants.kt
@@ -2,3 +2,5 @@ package com.audiobookshelf.app.player
const val CUSTOM_ACTION_JUMP_FORWARD = "com.audiobookshelf.customAction.jump_forward";
const val CUSTOM_ACTION_JUMP_BACKWARD = "com.audiobookshelf.customAction.jump_backward";
+const val CUSTOM_ACTION_SKIP_FORWARD = "com.audiobookshelf.customAction.skip_forward";
+const val CUSTOM_ACTION_SKIP_BACKWARD = "com.audiobookshelf.customAction.skip_backward";
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
index 92a0cdde..0f2c3e6e 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
@@ -45,6 +45,8 @@ import kotlin.concurrent.schedule
const val SLEEP_TIMER_WAKE_UP_EXPIRATION = 120000L // 2m
+const val PLAYER_CAST = "cast-player";
+const val PLAYER_EXO = "exo-player";
class PlayerNotificationService : MediaBrowserServiceCompat() {
@@ -256,6 +258,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
mediaSessionConnector = MediaSessionConnector(mediaSession)
val queueNavigator: TimelineQueueNavigator = object : TimelineQueueNavigator(mediaSession) {
+ override fun getSupportedQueueNavigatorActions(player: Player): Long {
+ return PlaybackStateCompat.ACTION_PLAY_PAUSE or PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE
+ }
+
override fun getMediaDescription(player: Player, windowIndex: Int): MediaDescriptionCompat {
if (currentPlaybackSession == null) {
Log.e(tag,"Playback session is not set - returning blank MediaDescriptionCompat")
@@ -296,11 +302,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
mediaSessionConnector.setQueueNavigator(queueNavigator)
mediaSessionConnector.setPlaybackPreparer(MediaSessionPlaybackPreparer(this))
- mediaSessionConnector.setCustomActionProviders(
- JumpForwardCustomActionProvider(),
- JumpBackwardCustomActionProvider(),
- )
-
mediaSession.setCallback(MediaSessionCallback(this))
initializeMPlayer()
@@ -343,19 +344,34 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
isClosed = false
+ val customActionProviders = mutableListOf(
+ JumpBackwardCustomActionProvider(),
+ JumpForwardCustomActionProvider(),
+ )
+ val metadata = playbackSession.getMediaMetadataCompat()
+ mediaSession.setMetadata(metadata)
+ val mediaItems = playbackSession.getMediaItems()
val playbackRateToUse = playbackRate ?: initialPlaybackRate ?: 1f
initialPlaybackRate = playbackRate
+ if (playbackSession.mediaPlayer != PLAYER_CAST && mediaItems.size > 1) {
+ customActionProviders.addAll(listOf(
+ SkipBackwardCustomActionProvider(),
+ SkipForwardCustomActionProvider(),
+ ));
+ }
+ mediaSessionConnector.setCustomActionProviders(*customActionProviders.toTypedArray());
+
playbackSession.mediaPlayer = getMediaPlayer()
- if (playbackSession.mediaPlayer == "cast-player" && playbackSession.isLocal) {
+ if (playbackSession.mediaPlayer == PLAYER_CAST && playbackSession.isLocal) {
Log.w(tag, "Cannot cast local media item - switching player")
currentPlaybackSession = null
switchToPlayer(false)
playbackSession.mediaPlayer = getMediaPlayer()
}
- if (playbackSession.mediaPlayer == "cast-player") {
+ if (playbackSession.mediaPlayer == PLAYER_CAST) {
// If cast-player is the first player to be used
mediaSessionConnector.setPlayer(castPlayer)
playerNotificationManager.setPlayer(castPlayer)
@@ -366,10 +382,6 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
clientEventEmitter?.onPlaybackSession(playbackSession)
- val metadata = playbackSession.getMediaMetadataCompat()
- mediaSession.setMetadata(metadata)
- val mediaItems = playbackSession.getMediaItems()
-
if (mediaItems.isEmpty()) {
Log.e(tag, "Invalid playback session no media items to play")
currentPlaybackSession = null
@@ -751,7 +763,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
fun getMediaPlayer():String {
- return if(currentPlayer == castPlayer) "cast-player" else "exo-player"
+ return if(currentPlayer == castPlayer) PLAYER_CAST else PLAYER_EXO
}
fun getDeviceInfo(): DeviceInfo {
@@ -1011,5 +1023,39 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
).build()
}
}
+
+ inner class SkipForwardCustomActionProvider : CustomActionProvider {
+ override fun onCustomAction(player: Player, action: String, extras: Bundle?) {
+ /*
+ This does not appear to ever get called. Instead, MediaSessionCallback.onCustomAction() is
+ responsible to reacting to a custom action.
+ */
+ }
+
+ override fun getCustomAction(player: Player): PlaybackStateCompat.CustomAction? {
+ return PlaybackStateCompat.CustomAction.Builder(
+ CUSTOM_ACTION_SKIP_FORWARD,
+ getContext().getString(R.string.action_skip_forward),
+ R.drawable.skip_next_24
+ ).build()
+ }
+ }
+
+ inner class SkipBackwardCustomActionProvider : CustomActionProvider {
+ override fun onCustomAction(player: Player, action: String, extras: Bundle?) {
+ /*
+ This does not appear to ever get called. Instead, MediaSessionCallback.onCustomAction() is
+ responsible to reacting to a custom action.
+ */
+ }
+
+ override fun getCustomAction(player: Player): PlaybackStateCompat.CustomAction? {
+ return PlaybackStateCompat.CustomAction.Builder(
+ CUSTOM_ACTION_SKIP_BACKWARD,
+ getContext().getString(R.string.action_skip_backward),
+ R.drawable.skip_previous_24
+ ).build()
+ }
+ }
}
diff --git a/android/app/src/main/res/drawable-anydpi/skip_next_24.xml b/android/app/src/main/res/drawable-anydpi/skip_next_24.xml
new file mode 100644
index 00000000..8c8a7482
--- /dev/null
+++ b/android/app/src/main/res/drawable-anydpi/skip_next_24.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable-anydpi/skip_previous_24.xml b/android/app/src/main/res/drawable-anydpi/skip_previous_24.xml
new file mode 100644
index 00000000..ee35a179
--- /dev/null
+++ b/android/app/src/main/res/drawable-anydpi/skip_previous_24.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/skip_next_24.xml b/android/app/src/main/res/drawable/skip_next_24.xml
new file mode 100644
index 00000000..d84d1d37
--- /dev/null
+++ b/android/app/src/main/res/drawable/skip_next_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/android/app/src/main/res/drawable/skip_previous_24.xml b/android/app/src/main/res/drawable/skip_previous_24.xml
new file mode 100644
index 00000000..3149ba4f
--- /dev/null
+++ b/android/app/src/main/res/drawable/skip_previous_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index dee17c07..c47bb9d8 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -8,4 +8,6 @@
Simple widget for audiobookshelf playback
Jump Forward
Jump Backward
+ Skip Forward
+ Skip Backward