Skip to content

Commit

Permalink
Show realtime and peak shake sensor value in dialog
Browse files Browse the repository at this point in the history
Fix threshold resetting to default when blank (disabled). Regression: 8dfb38d
Also disable when value is 0.
Don't require threshold to be exceeded in two consecutive readings.
  • Loading branch information
pilot51 committed May 20, 2024
1 parent f6db974 commit ff53685
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 30 deletions.
42 changes: 38 additions & 4 deletions app/src/main/java/com/pilot51/voicenotify/PreferenceDialogs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ import com.pilot51.voicenotify.db.Settings.Companion.DEFAULT_SPEAK_SCREEN_ON
import com.pilot51.voicenotify.db.Settings.Companion.DEFAULT_SPEAK_SILENT_ON
import com.pilot51.voicenotify.db.Settings.Companion.DEFAULT_TTS_STREAM
import com.pilot51.voicenotify.db.Settings.Companion.DEFAULT_TTS_STRING
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.seconds

private fun openBrowser(context: Context, url: String) {
try {
Expand All @@ -74,14 +78,44 @@ fun ShakeThresholdDialog(
onDismiss: () -> Unit
) {
val value by vm.getShakeThreshold()
var realtimeShake by remember { mutableIntStateOf(0) }
var peak by remember { mutableIntStateOf(0) }
val context = LocalContext.current
val scope = rememberCoroutineScope()
DisposableEffect(value) {
val shake = Shake(context)
scope.launch {
var peakTimeoutJob: Job? = null
shake.enable()
shake.jerk.collect {
realtimeShake = it.toInt()
if (realtimeShake > peak) {
peakTimeoutJob?.cancel()
peak = realtimeShake
peakTimeoutJob = launch {
delay(5.seconds)
peak = 0
}
}
}
}
onDispose {
shake.disable()
}
}
TextEditDialog(
titleRes = R.string.shake_to_silence,
message = stringResource(R.string.shake_to_silence_dialog_msg, DEFAULT_SHAKE_THRESHOLD),
initialText = value.toString(),
message = stringResource(
R.string.shake_to_silence_dialog_msg,
DEFAULT_SHAKE_THRESHOLD,
realtimeShake,
peak
),
initialText = value.takeIf { it > 0 }?.toString() ?: "",
keyboardType = KeyboardType.Number,
onDismiss = onDismiss
) {
vm.setShakeThreshold(it.toIntOrNull())
) { str ->
vm.setShakeThreshold(str.toIntOrNull()?.takeIf { it > 0 })
}
}

Expand Down
7 changes: 4 additions & 3 deletions app/src/main/java/com/pilot51/voicenotify/PreferenceHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ object PreferenceHelper {
private suspend fun initSettings() {
if (settingsDao.hasGlobalSettings()) return
val spDir = File(appContext.applicationInfo.dataDir, "shared_prefs")
val spName = "com.pilot51.voicenotify_preferences"
val spName = "${BuildConfig.APPLICATION_ID}_preferences"
val spFile = File(spDir, "$spName.xml")
if (spFile.exists()) {
val sp = PreferenceManager.getDefaultSharedPreferences(appContext)
Expand Down Expand Up @@ -130,8 +130,9 @@ object PreferenceHelper {
?.toDoubleOrNull() ?: 0.0
))
dataStore.edit { prefs ->
prefs[KEY_SHAKE_THRESHOLD] = sp.getString("shake_threshold", null)
?.toDoubleOrNull()?.roundToInt() ?: DEFAULT_SHAKE_THRESHOLD
sp.getString("shake_threshold", null)?.toDoubleOrNull()?.roundToInt()?.let {
prefs[KEY_SHAKE_THRESHOLD] = it
}
prefs[KEY_APP_DEFAULT_ENABLE] = sp.getBoolean("defEnable", DEFAULT_APP_DEFAULT_ENABLE)
prefs[KEY_IS_SUSPENDED] = sp.getBoolean("isSuspended", DEFAULT_IS_SUSPENDED)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pilot51.voicenotify.PreferenceHelper.DEFAULT_SHAKE_THRESHOLD
import com.pilot51.voicenotify.PreferenceHelper.KEY_SHAKE_THRESHOLD
import com.pilot51.voicenotify.PreferenceHelper.setPref
import com.pilot51.voicenotify.db.App
import com.pilot51.voicenotify.db.AppDatabase
import com.pilot51.voicenotify.db.Settings
Expand Down Expand Up @@ -65,15 +64,18 @@ class PreferencesViewModel : ViewModel(), IPreferencesViewModel {

@Composable
override fun getShakeThreshold(): State<Int> {
val default = DEFAULT_SHAKE_THRESHOLD
return if (isPreview) {
remember { mutableIntStateOf(default) }
remember { mutableIntStateOf(DEFAULT_SHAKE_THRESHOLD) }
} else {
PreferenceHelper.getPrefFlow(KEY_SHAKE_THRESHOLD, default)
.collectAsState(initial = default)
PreferenceHelper.getPrefFlow(KEY_SHAKE_THRESHOLD, 0)
.collectAsState(initial = 0)
}
}

override fun setShakeThreshold(threshold: Int?) {
PreferenceHelper.setPref(KEY_SHAKE_THRESHOLD, threshold)
}

override fun getApp(appPkg: String) = runBlocking(Dispatchers.IO) {
AppDatabase.db.appDao.get(appPkg)
}
Expand All @@ -97,10 +99,6 @@ class PreferencesViewModel : ViewModel(), IPreferencesViewModel {
}
}

override fun setShakeThreshold(threshold: Int?) {
setPref(KEY_SHAKE_THRESHOLD, threshold)
}

override fun getTtsTextReplace(settings: Settings) = convertTextReplaceStringToList(settings.ttsTextReplace)

override fun saveTtsTextReplace(
Expand Down
25 changes: 12 additions & 13 deletions app/src/main/java/com/pilot51/voicenotify/Shake.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import com.pilot51.voicenotify.PreferenceHelper.DEFAULT_SHAKE_THRESHOLD
import android.util.Log
import com.pilot51.voicenotify.PreferenceHelper.KEY_SHAKE_THRESHOLD
import com.pilot51.voicenotify.PreferenceHelper.getPrefFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import kotlin.math.abs
import kotlin.math.sqrt
Expand All @@ -37,27 +39,29 @@ class Shake(context: Context) : SensorEventListener {
var onShake: (() -> Unit)? = null
private var thresholdJob: Job? = null
private var threshold = 0
private var overThresholdCount = 0
private var accelCurrent = 0f
private var accelLast = 0f
private val _jerk = MutableStateFlow(0f)
val jerk: StateFlow<Float> = _jerk

fun enable() {
if (onShake == null) return
Log.i(TAG, "Shake listener enabled")
thresholdJob?.cancel()
thresholdJob = CoroutineScope(Dispatchers.IO).launch {
getPrefFlow(KEY_SHAKE_THRESHOLD, DEFAULT_SHAKE_THRESHOLD).collect {
getPrefFlow(KEY_SHAKE_THRESHOLD, 0).collect {
threshold = it
}
}
manager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL)
}

fun disable() {
Log.i(TAG, "Shake listener disabled")
thresholdJob?.cancel()
thresholdJob = null
manager.unregisterListener(this)
accelCurrent = 0f
accelLast = 0f
overThresholdCount = 0
}

override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
Expand All @@ -67,14 +71,9 @@ class Shake(context: Context) : SensorEventListener {
val y = event.values[1]
val z = event.values[2]
accelCurrent = sqrt((x * x + y * y + z * z).toDouble()).toFloat()
val accel = accelCurrent - accelLast
if (accelLast != 0f && abs(accel) > threshold / 10) {
overThresholdCount++
if (overThresholdCount >= 2) {
onShake!!.invoke()
}
} else {
overThresholdCount = 0
_jerk.value = if (accelLast != 0f) abs(accelCurrent - accelLast) * 10 else 0f
if (threshold > 0 && jerk.value >= threshold) {
onShake?.invoke()
}
accelLast = accelCurrent
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<string name="audio_focus_summary">Request other media to pause/dim when speaking</string>
<string name="shake_to_silence">Shake-To-Silence</string>
<string name="shake_to_silence_summary">Adjust the sensitivity threshold of Shake-To-Silence</string>
<string name="shake_to_silence_dialog_msg">Lower values are more sensitive.\n\nDefault: %d\nBlank to disable.</string>
<string name="shake_to_silence_dialog_msg">Lower values are more sensitive.\n\nDefault: %1$d\nBlank or 0 to disable.\n\nRealtime shake value: %2$d\nPeak (5 seconds): %3$d</string>
<string-array name="stream_name">
<item>Media</item>
<item>Notification</item>
Expand Down

0 comments on commit ff53685

Please sign in to comment.