Add:Android device setting to adjust shake sensitivity for sleep timer #260

This commit is contained in:
advplyr
2023-01-28 17:31:52 -06:00
parent f06afbd08c
commit 28e50dd461
9 changed files with 115 additions and 70 deletions
@@ -2,6 +2,7 @@ package com.audiobookshelf.app.data
import android.content.Context
import android.support.v4.media.MediaDescriptionCompat
import android.util.Log
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.fasterxml.jackson.annotation.JsonSubTypes
@@ -15,6 +16,10 @@ enum class HapticFeedbackSetting {
OFF, LIGHT, MEDIUM, HEAVY
}
enum class ShakeSensitivitySetting {
VERY_LOW, LOW, MEDIUM, HIGH, VERY_HIGH
}
data class ServerConnectionConfig(
var id:String,
var index:Int,
@@ -26,50 +31,6 @@ data class ServerConnectionConfig(
var customHeaders:Map<String, String>?
)
data class DeviceSettings(
var disableAutoRewind:Boolean,
var enableAltView:Boolean,
var jumpBackwardsTime:Int,
var jumpForwardTime:Int,
var disableShakeToResetSleepTimer:Boolean,
var lockOrientation:LockOrientationSetting,
var hapticFeedback: HapticFeedbackSetting
) {
companion object {
// Static method to get default device settings
fun default():DeviceSettings {
return DeviceSettings(
disableAutoRewind = false,
enableAltView = false,
jumpBackwardsTime = 10,
jumpForwardTime = 10,
disableShakeToResetSleepTimer = false,
lockOrientation = LockOrientationSetting.NONE,
hapticFeedback = HapticFeedbackSetting.LIGHT
)
}
}
@get:JsonIgnore
val jumpBackwardsTimeMs get() = (jumpBackwardsTime ?: default().jumpBackwardsTime) * 1000L
@get:JsonIgnore
val jumpForwardTimeMs get() = (jumpForwardTime ?: default().jumpForwardTime) * 1000L
}
data class DeviceData(
var serverConnectionConfigs:MutableList<ServerConnectionConfig>,
var lastServerConnectionConfigId:String?,
var currentLocalPlaybackSession:PlaybackSession?, // Stored to open up where left off for local media
var deviceSettings:DeviceSettings?
) {
@JsonIgnore
fun getLastServerConnectionConfig():ServerConnectionConfig? {
return lastServerConnectionConfigId?.let { lsccid ->
return serverConnectionConfigs.find { it.id == lsccid }
}
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
data class LocalFile(
var id:String,
@@ -127,3 +88,64 @@ data class PlayItemRequestPayload(
var forceTranscode:Boolean,
var deviceInfo:DeviceInfo
)
@JsonIgnoreProperties(ignoreUnknown = true)
data class DeviceSettings(
var disableAutoRewind:Boolean,
var enableAltView:Boolean,
var jumpBackwardsTime:Int,
var jumpForwardTime:Int,
var disableShakeToResetSleepTimer:Boolean,
var shakeSensitivity: ShakeSensitivitySetting,
var lockOrientation: LockOrientationSetting,
var hapticFeedback: HapticFeedbackSetting
) {
companion object {
// Static method to get default device settings
fun default():DeviceSettings {
return DeviceSettings(
disableAutoRewind = false,
enableAltView = false,
jumpBackwardsTime = 10,
jumpForwardTime = 10,
disableShakeToResetSleepTimer = false,
shakeSensitivity = ShakeSensitivitySetting.MEDIUM,
lockOrientation = LockOrientationSetting.NONE,
hapticFeedback = HapticFeedbackSetting.LIGHT
)
}
}
@get:JsonIgnore
val jumpBackwardsTimeMs get() = jumpBackwardsTime * 1000L
@get:JsonIgnore
val jumpForwardTimeMs get() = jumpForwardTime * 1000L
@JsonIgnore
fun getShakeThresholdGravity() : Float { // Used in ShakeDetector
return if (shakeSensitivity == ShakeSensitivitySetting.VERY_HIGH) 1.2f
else if (shakeSensitivity == ShakeSensitivitySetting.HIGH) 1.4f
else if (shakeSensitivity == ShakeSensitivitySetting.MEDIUM) 1.6f
else if (shakeSensitivity == ShakeSensitivitySetting.LOW) 2f
else if (shakeSensitivity == ShakeSensitivitySetting.VERY_LOW) 2.7f
else {
Log.e("DeviceSetting", "Invalid ShakeSensitivitySetting $shakeSensitivity")
1.6f
}
}
}
data class DeviceData(
var serverConnectionConfigs:MutableList<ServerConnectionConfig>,
var lastServerConnectionConfigId:String?,
var currentLocalPlaybackSession: PlaybackSession?, // Stored to open up where left off for local media
var deviceSettings: DeviceSettings?
) {
@JsonIgnore
fun getLastServerConnectionConfig(): ServerConnectionConfig? {
return lastServerConnectionConfigId?.let { lsccid ->
return serverConnectionConfigs.find { it.id == lsccid }
}
}
}
@@ -13,7 +13,7 @@ object DeviceManager {
const val tag = "DeviceManager"
val dbManager: DbManager = DbManager()
var deviceData:DeviceData = dbManager.getDeviceData()
var deviceData: DeviceData = dbManager.getDeviceData()
var serverConnectionConfig: ServerConnectionConfig? = null
val serverConnectionConfigId get() = serverConnectionConfig?.id ?: ""
@@ -10,7 +10,6 @@ import com.arthenica.ffmpegkit.FFprobeKit
import com.arthenica.ffmpegkit.Level
import com.audiobookshelf.app.data.*
import com.audiobookshelf.app.models.DownloadItem
import com.audiobookshelf.app.plugins.AbsDownloader
import com.fasterxml.jackson.core.json.JsonReadFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.readValue
@@ -12,16 +12,6 @@ import kotlin.math.roundToInt
const val SLEEP_EXTENSION_TIME = 900000L // 15m
class ShakeSensitivity {
companion object {
val veryHigh = 1f
val high = 1.3f
val medium = 1.6f
val low = 2f
val veryLow = 2.7f
}
}
class SleepTimerManager constructor(val playerNotificationService: PlayerNotificationService) {
private val tag = "SleepTimerManager"
@@ -194,8 +184,8 @@ class SleepTimerManager constructor(val playerNotificationService: PlayerNotific
return
}
// Does not apply to chapter sleep timers
if (sleepTimerEndTime == 0L) {
// Does not apply to chapter sleep timers and timer must be running for at least 3 seconds
if (sleepTimerEndTime == 0L && sleepTimerElapsed > 3000L) {
vibrate()
setSleepTimer(sleepTimerExtensionTime, false)
}
@@ -35,7 +35,6 @@ import com.audiobookshelf.app.managers.DbManager
import com.audiobookshelf.app.managers.SleepTimerManager
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
@@ -849,8 +848,7 @@ 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()
private val deviceSettings get() = DeviceManager.deviceData.deviceSettings ?: DeviceSettings.default()
fun getPlayItemRequestPayload(forceTranscode:Boolean):PlayItemRequestPayload {
return PlayItemRequestPayload(getMediaPlayer(), !forceTranscode, forceTranscode, getDeviceInfo())
@@ -1046,7 +1044,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
// Shake sensor used for sleep timer
fun registerSensor() {
if (isShakeSensorRegistered) {
Log.w(tag, "Shake sensor already registered")
Log.i(tag, "Shake sensor already registered")
return
}
shakeSensorUnregisterTask?.cancel()
@@ -4,6 +4,7 @@ import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import com.audiobookshelf.app.device.DeviceManager
import kotlin.math.sqrt
class ShakeDetector : SensorEventListener {
@@ -34,7 +35,8 @@ class ShakeDetector : SensorEventListener {
val gZ = z / SensorManager.GRAVITY_EARTH
// gForce will be close to 1 when there is no movement.
val gForce: Float = sqrt(gX * gX + gY * gY + gZ * gZ)
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
val shakeThreshold = DeviceManager.deviceData.deviceSettings?.getShakeThresholdGravity() ?: 1.6f
if (gForce > shakeThreshold) {
val now = System.currentTimeMillis()
// ignore shake events too close to each other (500ms)
if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
@@ -59,7 +61,7 @@ class ShakeDetector : SensorEventListener {
* from the Google Play Store and run it to see how
* many G's it takes to register a shake
*/
var SHAKE_THRESHOLD_GRAVITY = 1.5f // orig 2.7f
// var SHAKE_THRESHOLD_GRAVITY = 1.5f // orig 2.7f
private const val SHAKE_SLOP_TIME_MS = 500
private const val SHAKE_COUNT_RESET_TIME_MS = 3000
}
@@ -17,7 +17,7 @@ import kotlinx.coroutines.launch
@CapacitorPlugin(name = "AbsDatabase")
class AbsDatabase : Plugin() {
val tag = "AbsDatabase"
var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
private var jacksonMapper = jacksonObjectMapper().enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS.mappedFeature())
lateinit var mainActivity: MainActivity
lateinit var apiHandler: ApiHandler