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 714098fd..b81c67da 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
@@ -37,9 +37,9 @@ data class DeviceSettings(
}
@get:JsonIgnore
- val jumpBackwardsTimeMs get() = jumpBackwardsTime * 1000L
+ val jumpBackwardsTimeMs get() = (jumpBackwardsTime ?: default().jumpBackwardsTime) * 1000L
@get:JsonIgnore
- val jumpForwardTimeMs get() = jumpForwardTime * 1000L
+ val jumpForwardTimeMs get() = (jumpForwardTime ?: default().jumpBackwardsTime) * 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 3809286d..63460461 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
@@ -7,10 +7,8 @@ import android.os.Handler
import android.os.Looper
import android.os.Message
import android.support.v4.media.session.MediaSessionCompat
-import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import android.view.KeyEvent
-import com.audiobookshelf.app.R
import com.audiobookshelf.app.data.LibraryItemWrapper
import com.audiobookshelf.app.data.PodcastEpisode
import java.util.*
@@ -21,7 +19,6 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
private var mediaButtonClickCount: Int = 0
var mediaButtonClickTimeout: Long = 1000 //ms
- var seekAmount: Long = 20000 //ms
override fun onPrepare() {
Log.d(tag, "ON PREPARE MEDIA SESSION COMPAT")
@@ -75,19 +72,19 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
}
override fun onSkipToPrevious() {
- playerNotificationService.seekBackward(seekAmount)
+ playerNotificationService.skipToPrevious()
}
override fun onSkipToNext() {
- playerNotificationService.seekForward(seekAmount)
+ playerNotificationService.skipToNext()
}
override fun onFastForward() {
- playerNotificationService.seekForward(seekAmount)
+ playerNotificationService.jumpForward()
}
override fun onRewind() {
- playerNotificationService.seekForward(seekAmount)
+ playerNotificationService.jumpBackward()
}
override fun onSeekTo(pos: Long) {
@@ -179,10 +176,10 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
handleMediaButtonClickCount()
}
KeyEvent.KEYCODE_MEDIA_NEXT -> {
- playerNotificationService.seekForward(seekAmount)
+ playerNotificationService.jumpForward()
}
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> {
- playerNotificationService.seekBackward(seekAmount)
+ playerNotificationService.jumpBackward()
}
KeyEvent.KEYCODE_MEDIA_STOP -> {
playerNotificationService.closePlayback()
@@ -226,22 +223,22 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
if (2 == msg.what) {
- playerNotificationService.seekBackward(seekAmount)
+ playerNotificationService.jumpBackward()
playerNotificationService.play()
}
else if (msg.what >= 3) {
- playerNotificationService.seekForward(seekAmount)
+ playerNotificationService.jumpForward()
playerNotificationService.play()
}
}
}
- // Example Using a custom action in android auto
-// override fun onCustomAction(action: String?, extras: Bundle?) {
-// super.onCustomAction(action, extras)
-//
-// if ("com.audiobookshelf.app.PLAYBACK_RATE" == action) {
-//
-// }
-// }
+ override fun onCustomAction(action: String?, extras: Bundle?) {
+ super.onCustomAction(action, extras)
+
+ when (action) {
+ CUSTOM_ACTION_JUMP_FORWARD -> onFastForward()
+ CUSTOM_ACTION_JUMP_BACKWARD -> onRewind()
+ }
+ }
}
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
new file mode 100644
index 00000000..407425f8
--- /dev/null
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerConstants.kt
@@ -0,0 +1,4 @@
+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";
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 eb313b6c..92a0cdde 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
@@ -20,7 +20,6 @@ import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
-import androidx.core.content.res.ResourcesCompat
import androidx.media.MediaBrowserServiceCompat
import androidx.media.utils.MediaConstants
import com.audiobookshelf.app.BuildConfig
@@ -30,9 +29,11 @@ import com.audiobookshelf.app.data.DeviceInfo
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.media.MediaManager
import com.audiobookshelf.app.server.ApiHandler
+import com.fasterxml.jackson.annotation.JsonIgnore
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
+import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector.CustomActionProvider
import com.google.android.exoplayer2.ext.mediasession.TimelineQueueNavigator
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
@@ -42,6 +43,7 @@ import com.google.android.exoplayer2.upstream.*
import java.util.*
import kotlin.concurrent.schedule
+
const val SLEEP_TIMER_WAKE_UP_EXPIRATION = 120000L // 2m
class PlayerNotificationService : MediaBrowserServiceCompat() {
@@ -294,17 +296,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
mediaSessionConnector.setQueueNavigator(queueNavigator)
mediaSessionConnector.setPlaybackPreparer(MediaSessionPlaybackPreparer(this))
- // Example adding custom action with icon in android auto
-// mediaSessionConnector.setCustomActionProviders(object : MediaSessionConnector.CustomActionProvider {
-// override fun onCustomAction(player: Player, action: String, extras: Bundle?) {
-// }
-// override fun getCustomAction(player: Player): PlaybackStateCompat.CustomAction? {
-// var icon = R.drawable.exo_icon_rewind
-// return PlaybackStateCompat.CustomAction.Builder(
-// "com.audiobookshelf.app.PLAYBACK_RATE", "Playback Rate", icon)
-// .build()
-// }
-// })
+ mediaSessionConnector.setCustomActionProviders(
+ JumpForwardCustomActionProvider(),
+ JumpBackwardCustomActionProvider(),
+ )
mediaSession.setCallback(MediaSessionCallback(this))
@@ -320,13 +315,10 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
1000 * 20 // 20s playback rebuffer
).build()
- val seekBackTime = DeviceManager.deviceData.deviceSettings?.jumpBackwardsTimeMs ?: 10000
- val seekForwardTime = DeviceManager.deviceData.deviceSettings?.jumpForwardTimeMs ?: 10000
-
mPlayer = ExoPlayer.Builder(this)
.setLoadControl(customLoadControl)
- .setSeekBackIncrementMs(seekBackTime)
- .setSeekForwardIncrementMs(seekForwardTime)
+ .setSeekBackIncrementMs(deviceSettings.jumpBackwardsTimeMs)
+ .setSeekForwardIncrementMs(deviceSettings.jumpForwardTimeMs)
.build()
mPlayer.setHandleAudioBecomingNoisy(true)
mPlayer.addListener(PlayerListener(this))
@@ -701,6 +693,22 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
}
+ fun skipToPrevious() {
+ currentPlayer.seekToPrevious()
+ }
+
+ fun skipToNext() {
+ currentPlayer.seekToNext()
+ }
+
+ fun jumpForward() {
+ seekForward(deviceSettings.jumpForwardTimeMs)
+ }
+
+ fun jumpBackward() {
+ seekBackward(deviceSettings.jumpBackwardsTimeMs)
+ }
+
fun seekForward(amount: Long) {
seekPlayer(getCurrentTime() + amount)
}
@@ -757,6 +765,9 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
return DeviceInfo(Build.MANUFACTURER, Build.MODEL, Build.BRAND, Build.VERSION.SDK_INT, BuildConfig.VERSION_NAME)
}
+ @get:JsonIgnore
+ val deviceSettings get() = DeviceManager.deviceData.deviceSettings ?: DeviceSettings.default()
+
fun getPlayItemRequestPayload(forceTranscode:Boolean):PlayItemRequestPayload {
return PlayItemRequestPayload(getMediaPlayer(), !forceTranscode, forceTranscode, getDeviceInfo())
}
@@ -966,5 +977,39 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
clientEventEmitter?.onNetworkMeteredChanged(unmetered)
}
}
+
+ inner class JumpBackwardCustomActionProvider : 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_JUMP_BACKWARD,
+ getContext().getString(R.string.action_jump_backward),
+ R.drawable.exo_icon_rewind
+ ).build()
+ }
+ }
+
+ inner class JumpForwardCustomActionProvider : 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_JUMP_FORWARD,
+ getContext().getString(R.string.action_jump_forward),
+ R.drawable.exo_icon_fastforward
+ ).build()
+ }
+ }
}
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index b0944308..dee17c07 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -6,4 +6,6 @@
com.audiobookshelf.app
Add widget
Simple widget for audiobookshelf playback
+ Jump Forward
+ Jump Backward
diff --git a/android/build.gradle b/android/build.gradle
index 0e60006a..0df3fa91 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -8,8 +8,8 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath 'com.google.gms:google-services:4.3.5'
- classpath 'com.android.tools.build:gradle:7.2.0-beta04'
+ classpath 'com.google.gms:google-services:4.3.10'
+ classpath 'com.android.tools.build:gradle:7.2.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong