From de02a61c6efae6b2b07b43bb374c857c137ce5f4 Mon Sep 17 00:00:00 2001 From: Ashutosh Gangwar Date: Sun, 20 Nov 2022 14:36:48 +0530 Subject: [PATCH] feat(app): add user setting to gradually ramp up alarm ringer volume resolves https://github.com/trynoice/android-app/issues/1095 --- .../noice/repository/SettingsRepository.kt | 7 ++++ .../noice/service/AlarmRingerService.kt | 40 ++++++++++++++++++- app/src/main/res/values/donottranslate.xml | 1 + app/src/main/res/values/integers.xml | 1 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/settings.xml | 11 +++++ .../repository/SettingsRepositoryTest.kt | 18 +++++++++ .../noice/service/AlarmRingerServiceTest.kt | 5 +++ 8 files changed, 83 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/github/ashutoshgngwr/noice/repository/SettingsRepository.kt b/app/src/main/java/com/github/ashutoshgngwr/noice/repository/SettingsRepository.kt index 80447aa3f..5deb5b65a 100644 --- a/app/src/main/java/com/github/ashutoshgngwr/noice/repository/SettingsRepository.kt +++ b/app/src/main/java/com/github/ashutoshgngwr/noice/repository/SettingsRepository.kt @@ -203,6 +203,13 @@ class SettingsRepository @Inject constructor( ).toDuration(DurationUnit.MINUTES) } + fun getAlarmVolumeRampDuration(): Duration { + return prefs.getInt( + context.getString(R.string.alarm_gradually_increase_volume_key), + context.resources.getInteger(R.integer.default_alarm_gradually_increase_volume_minutes), + ).toDuration(DurationUnit.MINUTES) + } + private fun keyFlow(@StringRes keyStrRes: Int): Flow { return prefs.keyFlow(context.getString(keyStrRes)) } diff --git a/app/src/main/java/com/github/ashutoshgngwr/noice/service/AlarmRingerService.kt b/app/src/main/java/com/github/ashutoshgngwr/noice/service/AlarmRingerService.kt index 5e9f9eca8..7cf44483b 100644 --- a/app/src/main/java/com/github/ashutoshgngwr/noice/service/AlarmRingerService.kt +++ b/app/src/main/java/com/github/ashutoshgngwr/noice/service/AlarmRingerService.kt @@ -40,11 +40,15 @@ import com.github.ashutoshgngwr.noice.repository.PresetRepository import com.github.ashutoshgngwr.noice.repository.SettingsRepository import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.delay import kotlinx.coroutines.flow.lastOrNull +import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import javax.inject.Inject +import kotlin.math.min import kotlin.random.Random +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds @AndroidEntryPoint @@ -66,6 +70,7 @@ class AlarmRingerService : LifecycleService(), AudioFocusManager.Listener { internal lateinit var uiController: UiController private var defaultRingtonePlayer: MediaPlayer? = null + private var masterVolumeFadeJob: Job? = null private var autoDismissJob: Job? = null private val notificationManager: NotificationManager by lazy { requireNotNull(getSystemService()) } @@ -181,17 +186,45 @@ class AlarmRingerService : LifecycleService(), AudioFocusManager.Listener { ?: presetRepository.generate(emptySet(), Random.nextInt(2, 6)) .lastOrNull()?.data // or attempt to generate one + val fadeDurationMillis = min( + settingsRepository.getAlarmVolumeRampDuration().inWholeMilliseconds, + (settingsRepository.getAlarmRingerMaxDuration() - 1.minutes).inWholeMilliseconds, + ) + if (preset != null) { Log.d(LOG_TAG, "startRinger: starting preset: $preset") playbackController.setAudioUsage(AudioAttributesCompat.USAGE_ALARM) + if (fadeDurationMillis > 0) playbackController.setMasterVolume(5) playbackController.play(preset) } else { Log.d(LOG_TAG, "startRinger: starting default ringtone") - playDefaultRingtone() + playDefaultRingtone(if (fadeDurationMillis > 0) 0.2f else 1f) buildPresetLoadFailedNotification(alarmTriggerTime) .also { notificationManager.notify(NOTIFICATION_ID_PRIMING, it) } } + masterVolumeFadeJob?.cancelAndJoin() + masterVolumeFadeJob = if (fadeDurationMillis > 0) { + lifecycleScope.launch { + val fadeStepMillis = fadeDurationMillis / (PlaybackController.MAX_MASTER_VOLUME - 5) + var volume = 5 + while (isActive) { + volume++ + playbackController.setMasterVolume(volume) + (volume.toFloat() / PlaybackController.MAX_MASTER_VOLUME) + .also { defaultRingtonePlayer?.setVolume(it, it) } + + if (volume >= PlaybackController.MAX_MASTER_VOLUME) { + break + } + + delay(fadeStepMillis) + } + } + } else { + null + } + if (alarm.vibrate) { startVibrating() } @@ -296,8 +329,10 @@ class AlarmRingerService : LifecycleService(), AudioFocusManager.Listener { alarmRepository.reportTrigger(alarmId, isSnoozed) vibrator.cancel() + masterVolumeFadeJob?.cancelAndJoin() playbackController.pause(true) playbackController.setAudioUsage(AudioAttributesCompat.USAGE_MEDIA) + playbackController.setMasterVolume(PlaybackController.MAX_MASTER_VOLUME) audioFocusManager.abandonFocus() defaultRingtonePlayer?.release() @@ -321,7 +356,7 @@ class AlarmRingerService : LifecycleService(), AudioFocusManager.Listener { stopSelf() } - private fun playDefaultRingtone() { + private fun playDefaultRingtone(initialVolume: Float) { defaultRingtonePlayer?.release() val ringtoneUri = getDefaultAlarmRingtoneUri() ?: return defaultRingtonePlayer = MediaPlayer().apply { @@ -333,6 +368,7 @@ class AlarmRingerService : LifecycleService(), AudioFocusManager.Listener { .setLegacyStreamType(AudioManager.STREAM_ALARM) .build() ) + setVolume(initialVolume, initialVolume) prepare() } diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index bfdce6172..c873e637b 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -41,6 +41,7 @@ use_material_you_colors alarm_snooze_length alarm_ringer_max_duration + alarm_gradually_increase_volume https://opencollective.com/noice https://play.google.com/store/apps/details?id=com.github.ashutoshgngwr.noice https://f-droid.org/app/com.github.ashutoshgngwr.noice diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml index 7ef213d6c..dcf72738b 100644 --- a/app/src/main/res/values/integers.xml +++ b/app/src/main/res/values/integers.xml @@ -4,4 +4,5 @@ 5 18 9 + 1 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3abe0d59..8b5c2a8fd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -347,4 +347,6 @@ Alarm missed No Presets Master Volume + Gradually increase alarm volume + Duration in minutes for gradually increasing the volume when an alarm fires \ No newline at end of file diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 3c0f6e3a5..2b5500ea5 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -100,6 +100,17 @@ app:seekBarIncrement="1" app:showSeekBarValue="true" /> + +