From e5b6cf7231ddf9b79da0b881e60fd35a9c5ebf00 Mon Sep 17 00:00:00 2001 From: Bart Sopers Date: Sat, 29 Aug 2020 05:37:26 +0200 Subject: [PATCH] Add option to gradually increase alarm volume --- app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/pref_alerts.xml | 5 ++ .../androidaps/services/AlarmSoundService.kt | 67 +++++++++++++++++-- core/src/main/res/values/strings.xml | 2 +- 4 files changed, 70 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d3bd9b86bf..17343701cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -657,6 +657,7 @@ Missed BG readings raise_urgent_alarms_as_android_notification Use system notifications for alerts and notifications + Gradually increase the volume for alerts and notifications enable_pump_unreachable_alert enable_missed_bg_readings enable_carbs_required_alert_local diff --git a/app/src/main/res/xml/pref_alerts.xml b/app/src/main/res/xml/pref_alerts.xml index a7783f7954..ebb71e5611 100644 --- a/app/src/main/res/xml/pref_alerts.xml +++ b/app/src/main/res/xml/pref_alerts.xml @@ -47,6 +47,11 @@ android:key="@string/key_raise_notifications_as_android_notifications" android:title="@string/raise_notifications_as_android_notifications" /> + + diff --git a/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.kt b/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.kt index f84e6af6e2..8f5eb74190 100644 --- a/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.kt +++ b/core/src/main/java/info/nightscout/androidaps/services/AlarmSoundService.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.media.AudioManager import android.media.MediaPlayer +import android.os.Handler import android.os.IBinder import dagger.android.DaggerService import info.nightscout.androidaps.core.R @@ -11,16 +12,38 @@ import info.nightscout.androidaps.interfaces.NotificationHolderInterface import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP import javax.inject.Inject +import kotlin.math.ln +import kotlin.math.pow class AlarmSoundService : DaggerService() { @Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var notificationHolder: NotificationHolderInterface + @Inject lateinit var sp: SP private var player: MediaPlayer? = null private var resourceId = R.raw.error + companion object { + private const val VOLUME_INCREASE_STEPS = 40; // Total number of steps to increase volume with + private const val VOLUME_INCREASE_INITIAL_SILENT_TIME_MILLIS = 3_000L; // Number of milliseconds that the notification should initially be silent + private const val VOLUME_INCREASE_BASE_DELAY_MILLIS = 15_000; // Base delay between volume increments + private const val VOLUME_INCREASE_MIN_DELAY_MILLIS = 2_000L; // Minimum delay between volume increments + + /* + * Delay until the next volumen increment will be the lowest value of VOLUME_INCREASE_MIN_DELAY_MILLIS and + * VOLUME_INCREASE_BASE_DELAY_MILLIS - (currentVolumeLevel - 1) ^ VOLUME_INCREASE_DELAY_DECREMENT_EXPONENT * 1000 + * + */ + private const val VOLUME_INCREASE_DELAY_DECREMENT_EXPONENT = 2.0; + + } + + private val handler = Handler() + private var currentVolumeLevel = 0 + override fun onBind(intent: Intent): IBinder? = null override fun onCreate() { @@ -41,10 +64,16 @@ class AlarmSoundService : DaggerService() { val afd = resourceHelper.openRawResourceFd(resourceId) ?: return START_STICKY player?.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length) afd.close() - player?.isLooping = true // Set looping - val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager - if (!manager.isMusicActive) { - player?.setVolume(100f, 100f) + player?.isLooping = true + val audioManager = getAudioManager(); + if (!audioManager.isMusicActive) { + if (sp.getBoolean(R.string.key_gradually_increase_notification_volume, false)) { + currentVolumeLevel = 0; + player?.setVolume(0f, 0f) + handler.postDelayed(volumeUpdater, VOLUME_INCREASE_INITIAL_SILENT_TIME_MILLIS) + } else { + player?.setVolume(1f, 1f) + } } player?.prepare() player?.start() @@ -55,8 +84,38 @@ class AlarmSoundService : DaggerService() { } override fun onDestroy() { + handler.removeCallbacks(volumeUpdater) player?.stop() player?.release() aapsLogger.debug(LTag.CORE, "onDestroy") } + + private fun getAudioManager(): AudioManager { + return getSystemService(Context.AUDIO_SERVICE) as AudioManager + } + + // TODO replace with VolumeShaper when min API level >= 26 + private val volumeUpdater = object : Runnable { + override fun run() { + if (player?.isPlaying == true) { + currentVolumeLevel++; + + val volumePercentage = 100.0.coerceAtMost(currentVolumeLevel / VOLUME_INCREASE_STEPS.toDouble() * 100) + val volume = 1 - (ln(1.0.coerceAtLeast(100.0 - volumePercentage)) / ln(100.0)) + + aapsLogger.debug(LTag.CORE, "Setting notification volume to {} ({} %)", volume, volumePercentage) + + val floatVolume = volume.toFloat() + player?.setVolume(floatVolume, floatVolume) + + if (currentVolumeLevel < VOLUME_INCREASE_STEPS) { + // Increase volume faster as time goes by + val delay = VOLUME_INCREASE_MIN_DELAY_MILLIS.coerceAtLeast(VOLUME_INCREASE_BASE_DELAY_MILLIS - + ((currentVolumeLevel - 1).toDouble().pow(VOLUME_INCREASE_DELAY_DECREMENT_EXPONENT) * 1000).toLong()) + aapsLogger.debug(LTag.CORE, "Next notification volume increment in {}ms", delay) + handler.postDelayed(this, delay); + } + } + } + } } \ No newline at end of file diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9ed19651f5..7d8c9b865b 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -22,6 +22,7 @@ ns_uploadlocalprofile bt_watchdog bt_watchdog_last + gradually_increase_notification_volume Pairing @@ -281,5 +282,4 @@ - \ No newline at end of file