fix: play through the alarm stream so the ring cuts through DND

DND silences the media stream by default, so playback on STREAM_MUSIC was
invisible during DND even though the notification showed. Switch to
STREAM_ALARM + USAGE_ALARM, which DND exempts by default, and restore/force
the alarm stream volume instead of media.
This commit is contained in:
avi 2026-08-07 13:37:29 -05:00
commit 5e5d53ab9b
2 changed files with 20 additions and 16 deletions

View file

@ -147,19 +147,20 @@ class RingService : Service() {
*/
private suspend fun beginPlayback(uri: Uri): Boolean {
return try {
// Step 1: save current volume.
originalVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
// Step 1: save current alarm-stream volume so we can restore it later.
originalVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM)
// Step 2: force max volume.
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
// Step 2: force the alarm stream to max volume.
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM)
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.STREAM_ALARM,
maxVolume,
0 // flags = 0 so we do NOT show the system volume UI.
)
// Step 3: request focus. Use USAGE_NOTIFICATION_RINGTONE so the
// system lets it play even during DND, and set MODE_RINGTONE.
// Step 3: request focus. Playing on the ALARM stream with
// USAGE_ALARM is what cuts through Do Not Disturb — DND does not
// silence alarms by default (unlike media/music).
previousFocusMode = audioManager.mode
requestAudioFocus()
@ -168,7 +169,7 @@ class RingService : Service() {
mediaPlayer = MediaPlayer()
mediaPlayer.setAudioAttributes(
AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
)
@ -215,7 +216,7 @@ class RingService : Service() {
}
val attributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
@ -230,7 +231,7 @@ class RingService : Service() {
@Suppress("DEPRECATION")
audioManager.requestAudioFocus(
listener,
AudioManager.STREAM_MUSIC,
AudioManager.STREAM_ALARM,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT
)
}
@ -276,7 +277,7 @@ class RingService : Service() {
// Restore the previous volume.
if (originalVolume >= 0) {
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
AudioManager.STREAM_ALARM,
originalVolume,
0
)