diff --git a/README.md b/README.md index 5b4e4b4..c19bbdc 100644 --- a/README.md +++ b/README.md @@ -49,11 +49,14 @@ refuse to play any sound.** This is enforced at two points: Only after the user flips that toggle will a trigger actually ring. When access **is** granted, `RingService`: -- saves the current music volume, -- forces `AudioManager.STREAM_MUSIC` to max, -- requests `AUDIOFOCUS_GAIN_TRANSIENT` using `USAGE_NOTIFICATION_RINGTONE` and - sets `AudioManager.mode = MODE_RINGTONE` so the sound cuts through DND, -- plays for 30 s, then restores the volume and abandons focus. +- saves the current **alarm-stream** volume, +- forces `AudioManager.STREAM_ALARM` to max, +- requests `AUDIOFOCUS_GAIN_TRANSIENT` using `AudioAttributes.USAGE_ALARM`, +- plays on the **alarm stream** — the one stream Do Not Disturb does **not** + silence by default (media/music *is* silenced), which is what lets the ring + cut through DND, +- plays for the configured number of seconds, then restores the volume and + abandons focus. --- diff --git a/app/src/main/java/com/example/lostmyphone/RingService.kt b/app/src/main/java/com/example/lostmyphone/RingService.kt index 45b46e7..ac24488 100644 --- a/app/src/main/java/com/example/lostmyphone/RingService.kt +++ b/app/src/main/java/com/example/lostmyphone/RingService.kt @@ -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 )