Add option to gradually increase alarm volume

This commit is contained in:
Bart Sopers 2020-08-29 05:37:26 +02:00
parent 134b79dd8a
commit e5b6cf7231
4 changed files with 70 additions and 5 deletions

View file

@ -657,6 +657,7 @@
<string name="missed_bg_readings">Missed BG readings</string> <string name="missed_bg_readings">Missed BG readings</string>
<string name="key_raise_notifications_as_android_notifications" translatable="false">raise_urgent_alarms_as_android_notification</string> <string name="key_raise_notifications_as_android_notifications" translatable="false">raise_urgent_alarms_as_android_notification</string>
<string name="raise_notifications_as_android_notifications">Use system notifications for alerts and notifications</string> <string name="raise_notifications_as_android_notifications">Use system notifications for alerts and notifications</string>
<string name="gradually_increase_notification_volume">Gradually increase the volume for alerts and notifications</string>
<string name="key_enable_pump_unreachable_alert" translatable="false">enable_pump_unreachable_alert</string> <string name="key_enable_pump_unreachable_alert" translatable="false">enable_pump_unreachable_alert</string>
<string name="key_enable_missed_bg_readings_alert" translatable="false">enable_missed_bg_readings</string> <string name="key_enable_missed_bg_readings_alert" translatable="false">enable_missed_bg_readings</string>
<string name="key_enable_carbs_required_alert_local" translatable="false">enable_carbs_required_alert_local</string> <string name="key_enable_carbs_required_alert_local" translatable="false">enable_carbs_required_alert_local</string>

View file

@ -47,6 +47,11 @@
android:key="@string/key_raise_notifications_as_android_notifications" android:key="@string/key_raise_notifications_as_android_notifications"
android:title="@string/raise_notifications_as_android_notifications" /> android:title="@string/raise_notifications_as_android_notifications" />
<SwitchPreference
android:defaultValue="false"
android:key="@string/key_gradually_increase_notification_volume"
android:title="@string/gradually_increase_notification_volume" />
</PreferenceCategory> </PreferenceCategory>
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

View file

@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.media.AudioManager import android.media.AudioManager
import android.media.MediaPlayer import android.media.MediaPlayer
import android.os.Handler
import android.os.IBinder import android.os.IBinder
import dagger.android.DaggerService import dagger.android.DaggerService
import info.nightscout.androidaps.core.R 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.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.ln
import kotlin.math.pow
class AlarmSoundService : DaggerService() { class AlarmSoundService : DaggerService() {
@Inject lateinit var aapsLogger: AAPSLogger @Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var resourceHelper: ResourceHelper @Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var notificationHolder: NotificationHolderInterface @Inject lateinit var notificationHolder: NotificationHolderInterface
@Inject lateinit var sp: SP
private var player: MediaPlayer? = null private var player: MediaPlayer? = null
private var resourceId = R.raw.error 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 onBind(intent: Intent): IBinder? = null
override fun onCreate() { override fun onCreate() {
@ -41,10 +64,16 @@ class AlarmSoundService : DaggerService() {
val afd = resourceHelper.openRawResourceFd(resourceId) ?: return START_STICKY val afd = resourceHelper.openRawResourceFd(resourceId) ?: return START_STICKY
player?.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length) player?.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length)
afd.close() afd.close()
player?.isLooping = true // Set looping player?.isLooping = true
val manager = getSystemService(Context.AUDIO_SERVICE) as AudioManager val audioManager = getAudioManager();
if (!manager.isMusicActive) { if (!audioManager.isMusicActive) {
player?.setVolume(100f, 100f) 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?.prepare()
player?.start() player?.start()
@ -55,8 +84,38 @@ class AlarmSoundService : DaggerService() {
} }
override fun onDestroy() { override fun onDestroy() {
handler.removeCallbacks(volumeUpdater)
player?.stop() player?.stop()
player?.release() player?.release()
aapsLogger.debug(LTag.CORE, "onDestroy") 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);
}
}
}
}
} }

View file

@ -22,6 +22,7 @@
<string name="key_ns_uploadlocalprofile" translatable="false">ns_uploadlocalprofile</string> <string name="key_ns_uploadlocalprofile" translatable="false">ns_uploadlocalprofile</string>
<string name="key_btwatchdog" translatable="false">bt_watchdog</string> <string name="key_btwatchdog" translatable="false">bt_watchdog</string>
<string name="key_btwatchdog_lastbark" translatable="false">bt_watchdog_last</string> <string name="key_btwatchdog_lastbark" translatable="false">bt_watchdog_last</string>
<string name="key_gradually_increase_notification_volume" translatable="false">gradually_increase_notification_volume</string>
<string name="pairing">Pairing</string> <string name="pairing">Pairing</string>
<!-- General--> <!-- General-->
@ -281,5 +282,4 @@
<!-- Unknown(R.string.medtronic_history_group_unknown), //--> <!-- Unknown(R.string.medtronic_history_group_unknown), //-->
</resources> </resources>