From f223138eb833a9f1a8e8d76d69db88bcb9f6d208 Mon Sep 17 00:00:00 2001 From: Jamie McDowell Date: Tue, 23 May 2023 00:30:33 +0100 Subject: [PATCH 1/4] Audio ducking now supported during notifications --- CHANGELOG.md | 2 + .../settings/NotificationsSettingsFragment.kt | 41 +++++++++++++++---- .../res/xml/preferences_notifications.xml | 11 +++-- .../src/main/res/values/strings.xml | 6 ++- .../pocketcasts/preferences/Settings.kt | 5 ++- .../pocketcasts/preferences/SettingsImpl.kt | 8 +++- .../repositories/playback/FocusManager.kt | 17 +++++--- .../repositories/playback/LocalPlayer.kt | 2 +- .../repositories/playback/PlaybackManager.kt | 9 ++-- .../repositories/support/Support.kt | 9 +++- 10 files changed, 81 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 844ddca6a37..2ca1732e692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,6 +64,8 @@ ([#973](https://github.com/Automattic/pocket-casts-android/pull/973)). * Improved the Automotive user profile view ([#975](https://github.com/Automattic/pocket-casts-android/pull/975)). + * Added audio ducking as an option when playing over external notifications + ([#1009](https://github.com/Automattic/pocket-casts-android/pull/1009)). 7.39 ----- diff --git a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt index c46c9eba726..08bb61c2ac6 100644 --- a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt +++ b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt @@ -71,6 +71,7 @@ class NotificationsSettingsFragment : private var enabledPreference: SwitchPreference? = null private var systemSettingsPreference: Preference? = null private var notificationActions: PreferenceScreen? = null + private var playOverNotificationPreference: ListPreference? = null private val toolbar get() = view?.findViewById(R.id.toolbar) @@ -95,6 +96,7 @@ class NotificationsSettingsFragment : vibratePreference = manager.findPreference("notificationVibrate") notificationActions = manager.findPreference("notificationActions") systemSettingsPreference = manager.findPreference("openSystemSettings") + playOverNotificationPreference = manager.findPreference("notificationAudio") // turn preferences off by default, because they are enable async, we don't want this view to remove them from the screen after it loads as it looks jarring enabledPreferences(false) @@ -111,13 +113,6 @@ class NotificationsSettingsFragment : updateNotificationsEnabled() manager.run { - findPreference(Settings.PREFERENCE_OVERRIDE_AUDIO)?.setOnPreferenceChangeListener { _, newValue -> - analyticsTracker.track( - AnalyticsEvent.SETTINGS_NOTIFICATIONS_PLAY_OVER_NOTIFICATIONS_TOGGLED, - mapOf("enabled" to newValue as Boolean) - ) - true - } findPreference(Settings.PREFERENCE_HIDE_NOTIFICATION_ON_PAUSE)?.setOnPreferenceChangeListener { _, newValue -> analyticsTracker.track( AnalyticsEvent.SETTINGS_NOTIFICATIONS_HIDE_PLAYBACK_NOTIFICATION_ON_PAUSE, @@ -140,6 +135,13 @@ class NotificationsSettingsFragment : ) true } + playOverNotificationPreference?.setOnPreferenceChangeListener { _, newValue -> + analyticsTracker.track( + AnalyticsEvent.SETTINGS_NOTIFICATIONS_PLAY_OVER_NOTIFICATIONS_TOGGLED, + mapOf("enabled" to (newValue != "2")) + ) + true + } } private fun updateNotificationsEnabled() { @@ -386,6 +388,7 @@ class NotificationsSettingsFragment : override fun onResume() { super.onResume() setupNotificationVibrate() + setupPlayOverNotifications() changePodcastsSummary() preferenceScreen.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) } @@ -398,6 +401,8 @@ class NotificationsSettingsFragment : override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { if (Settings.PREFERENCE_NOTIFICATION_VIBRATE == key) { changeVibrateSummary() + } else if (Settings.PREFERENCE_NOTIFICATION_AUDIO == key) { + changePlayOverNotificationSummary() } } @@ -452,6 +457,28 @@ class NotificationsSettingsFragment : } } + private fun setupPlayOverNotifications() { + playOverNotificationPreference?.let { + it.entries = arrayOf( + getString(LR.string.settings_notification_play_over_never), + getString(LR.string.settings_notification_play_over_duck), + getString(LR.string.settings_notification_play_over_always) + ) + it.entryValues = arrayOf("2", "1", "0") + it.value = settings.getPlayOverNotification().toString() + } + changePlayOverNotificationSummary() + } + + private fun changePlayOverNotificationSummary() { + playOverNotificationPreference?.summary = when (settings.getPlayOverNotification()) { + 2 -> getString(LR.string.settings_notification_play_over_never) + 1 -> getString(LR.string.settings_notification_play_over_duck) + 0 -> getString(LR.string.settings_notification_play_over_always) + else -> "" + } + } + override fun getBackstackCount(): Int { return childFragmentManager.backStackEntryCount } diff --git a/modules/features/settings/src/main/res/xml/preferences_notifications.xml b/modules/features/settings/src/main/res/xml/preferences_notifications.xml index b2b6b86a273..90b51bfd249 100644 --- a/modules/features/settings/src/main/res/xml/preferences_notifications.xml +++ b/modules/features/settings/src/main/res/xml/preferences_notifications.xml @@ -42,12 +42,11 @@ - + + Choose podcasts Hide playback notification on pause Notify me - Play over notifications - Keep playing even when other apps, like notifications or navigation, play sounds. + Play over external notifications + Never + Duck volume + Always Notification sound Notification sound played. Select 3 actions diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt index 762d6069606..1193e050b64 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt @@ -83,7 +83,8 @@ interface Settings { const val PREFERENCE_SELECT_PODCAST_LIBRARY_SORT = "selectPodcastLibrarySort" const val PREFERENCE_WARN_WHEN_NOT_ON_WIFI = "warnWhenNotOnWifi" const val PREFERENCE_SYNC_ON_METERED = "SyncWhenOnMetered" - const val PREFERENCE_OVERRIDE_AUDIO = "overrideAudioInterruption" + const val PREFERENCE_NOTIFICATION_AUDIO = "notificationAudio" + const val PREFERENCE_NOTIFICATION_AUDIO_DEFAULT = "2" const val PREFERENCE_USE_EMBEDDED_ARTWORK = "useEmbeddedArtwork" const val PREFERENCE_LAST_MODIFIED = "lastModified" const val PREFERENCE_FIRST_SYNC_RUN = "firstSyncRun" @@ -396,7 +397,7 @@ interface Settings { fun setPopularPodcastCountryCode(code: String) - fun canDuckAudioWithNotifications(): Boolean + fun getPlayOverNotification(): Int fun hasBlockAlreadyRun(label: String): Boolean fun setBlockAlreadyRun(label: String, hasRun: Boolean) diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt index 6457609ad37..b62546aa23c 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt @@ -504,8 +504,12 @@ class SettingsImpl @Inject constructor( return getBoolean(Settings.PREFERENCE_AUTO_SHOW_PLAYED, false) } - override fun canDuckAudioWithNotifications(): Boolean { - return sharedPreferences.getBoolean(Settings.PREFERENCE_OVERRIDE_AUDIO, false) + override fun getPlayOverNotification(): Int { + val value = sharedPreferences.getString( + Settings.PREFERENCE_NOTIFICATION_AUDIO, + Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT + ) ?: Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT + return Integer.parseInt(value) } override fun hasBlockAlreadyRun(label: String): Boolean { diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt index 1677cbadeb4..c1346e9e5b2 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt @@ -150,17 +150,24 @@ open class FocusManager(private val settings: Settings, context: Context?) : Aud } } - fun canDuck(): Boolean { - return audioFocus == AUDIO_NO_FOCUS_CAN_DUCK_TRANSIENT && hasUserAllowedDucking() + enum class PlayOverNotificationSetting { + NEVER, DUCK, ALWAYS } - protected open fun hasUserAllowedDucking(): Boolean { - return settings.canDuckAudioWithNotifications() + private fun canDuck(): PlayOverNotificationSetting { + if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK_TRANSIENT) return PlayOverNotificationSetting.NEVER + return playOverNotification() + } + + protected open fun playOverNotification() = when (settings.getPlayOverNotification()) { + 0 -> PlayOverNotificationSetting.ALWAYS + 1 -> PlayOverNotificationSetting.DUCK + else -> PlayOverNotificationSetting.NEVER } interface FocusChangeListener { fun onFocusGain(shouldResume: Boolean) - fun onFocusLoss(mayDuck: Boolean, transientLoss: Boolean) + fun onFocusLoss(playOverNotification: PlayOverNotificationSetting, transientLoss: Boolean) fun onFocusRequestFailed() } diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LocalPlayer.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LocalPlayer.kt index 2fae8022144..514e99e509e 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LocalPlayer.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LocalPlayer.kt @@ -14,7 +14,7 @@ abstract class LocalPlayer(override val onPlayerEvent: (Player, PlayerEvent) -> companion object { // The volume we set the media player to seekToTimeMswhen we lose audio focus, but are allowed to reduce the volume instead of stopping playback. - const val VOLUME_DUCK = 1.0f // We don't actually duck the volume + const val VOLUME_DUCK = 0.5f // The volume we set the media player when we have audio focus. const val VOLUME_NORMAL = 1.0f } diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt index 6019e7abbc2..d871706153e 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt @@ -1337,14 +1337,14 @@ open class PlaybackManager @Inject constructor( focusWasPlaying = null } - override fun onFocusLoss(mayDuck: Boolean, transientLoss: Boolean) { + override fun onFocusLoss(playOverNotification: FocusManager.PlayOverNotificationSetting, transientLoss: Boolean) { val player = player if (player == null || player.isRemote) { return } // if we are playing but can't just reduce the volume then play when focus gained val playing = isPlaying() - if (!mayDuck && playing) { + if ((playOverNotification == FocusManager.PlayOverNotificationSetting.NEVER) && playing) { LogBuffer.i(LogBuffer.TAG_PLAYBACK, "Focus lost while playing") focusWasPlaying = Date() @@ -1355,9 +1355,12 @@ open class PlaybackManager @Inject constructor( } // check if we need to reduce the volume - if (focusManager.canDuck()) { + if (playOverNotification == FocusManager.PlayOverNotificationSetting.DUCK) { player.setVolume(VOLUME_DUCK) + return } + + player.setVolume(VOLUME_NORMAL) } override fun onFocusRequestFailed() { diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt index 0f110904cc5..0130df69681 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt @@ -406,7 +406,7 @@ class Support @Inject constructor( output.append(eol) output.append("Notifications").append(eol) - output.append("Play over notifications? ").append(if (settings.canDuckAudioWithNotifications()) "yes" else "no").append(eol) + output.append("Play over notifications? ").append(playOverNotificationString(settings.getPlayOverNotification())).append(eol) output.append("Hide notification on pause? ").append(if (settings.hideNotificationOnPause()) "yes" else "no").append(eol) output.append(eol) @@ -475,6 +475,13 @@ class Support @Inject constructor( return if (value) "yes" else "no" } + private fun playOverNotificationString(value: Int) = when (value) { + 0 -> "always" + 1 -> "duck" + 2 -> "never" + else -> "unknown" + } + private fun getDeviceName(): String { try { return DeviceName.getDeviceName() From 3fdb8f89e7434696b7b94600031fafbc039b0636 Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Mon, 19 Jun 2023 16:44:26 -0400 Subject: [PATCH 2/4] POC using enum for notification play over setting --- .../settings/NotificationsSettingsFragment.kt | 33 ++++++++++------- .../PlayOverNotificationSetting.kt | 37 +++++++++++++++++++ .../pocketcasts/preferences/Settings.kt | 2 +- .../pocketcasts/preferences/SettingsImpl.kt | 4 +- .../repositories/playback/FocusManager.kt | 14 +------ .../repositories/playback/PlaybackManager.kt | 7 ++-- .../repositories/support/Support.kt | 9 +---- 7 files changed, 66 insertions(+), 40 deletions(-) create mode 100644 modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/PlayOverNotificationSetting.kt diff --git a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt index 08bb61c2ac6..67197f4fb66 100644 --- a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt +++ b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt @@ -16,6 +16,7 @@ import androidx.preference.PreferenceScreen import androidx.preference.SwitchPreference import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsEvent import au.com.shiftyjelly.pocketcasts.analytics.AnalyticsTrackerWrapper +import au.com.shiftyjelly.pocketcasts.preferences.PlayOverNotificationSetting import au.com.shiftyjelly.pocketcasts.preferences.Settings import au.com.shiftyjelly.pocketcasts.repositories.notification.NewEpisodeNotificationAction import au.com.shiftyjelly.pocketcasts.repositories.notification.NotificationHelper @@ -136,10 +137,18 @@ class NotificationsSettingsFragment : true } playOverNotificationPreference?.setOnPreferenceChangeListener { _, newValue -> + val playOverNotificationSetting = (newValue as? String) + ?.let { PlayOverNotificationSetting.fromPreferenceString(it) } + ?: throw IllegalStateException("Invalid value for play over notification preference: $newValue") + analyticsTracker.track( AnalyticsEvent.SETTINGS_NOTIFICATIONS_PLAY_OVER_NOTIFICATIONS_TOGGLED, - mapOf("enabled" to (newValue != "2")) + mapOf( + "enabled" to (playOverNotificationSetting != PlayOverNotificationSetting.NEVER), + "value" to playOverNotificationSetting.analyticsString, + ), ) + true } } @@ -458,25 +467,21 @@ class NotificationsSettingsFragment : } private fun setupPlayOverNotifications() { - playOverNotificationPreference?.let { - it.entries = arrayOf( - getString(LR.string.settings_notification_play_over_never), - getString(LR.string.settings_notification_play_over_duck), - getString(LR.string.settings_notification_play_over_always) + playOverNotificationPreference?.apply { + val options = listOf( + PlayOverNotificationSetting.NEVER, + PlayOverNotificationSetting.DUCK, + PlayOverNotificationSetting.ALWAYS, ) - it.entryValues = arrayOf("2", "1", "0") - it.value = settings.getPlayOverNotification().toString() + entries = options.map { getString(it.titleRes) }.toTypedArray() + entryValues = options.map { it.preferenceInt.toString() }.toTypedArray() + value = settings.getPlayOverNotification().preferenceInt.toString() } changePlayOverNotificationSummary() } private fun changePlayOverNotificationSummary() { - playOverNotificationPreference?.summary = when (settings.getPlayOverNotification()) { - 2 -> getString(LR.string.settings_notification_play_over_never) - 1 -> getString(LR.string.settings_notification_play_over_duck) - 0 -> getString(LR.string.settings_notification_play_over_always) - else -> "" - } + playOverNotificationPreference?.summary = getString(settings.getPlayOverNotification().titleRes) } override fun getBackstackCount(): Int { diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/PlayOverNotificationSetting.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/PlayOverNotificationSetting.kt new file mode 100644 index 00000000000..99dc80e6dda --- /dev/null +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/PlayOverNotificationSetting.kt @@ -0,0 +1,37 @@ +package au.com.shiftyjelly.pocketcasts.preferences + +import androidx.annotation.StringRes +import au.com.shiftyjelly.pocketcasts.localization.R as LR + +enum class PlayOverNotificationSetting( + val preferenceInt: Int, + @StringRes val titleRes: Int, + val analyticsString: String, +) { + NEVER( + titleRes = LR.string.settings_notification_play_over_never, + preferenceInt = 2, + analyticsString = "never" + ), + DUCK( + titleRes = LR.string.settings_notification_play_over_duck, + preferenceInt = 1, + analyticsString = "duck" + ), + ALWAYS( + titleRes = LR.string.settings_notification_play_over_always, + preferenceInt = 0, + analyticsString = "always" + ); + + companion object { + fun fromPreferenceString(stringValue: String): PlayOverNotificationSetting { + try { + val intValue = stringValue.toInt() + return values().first { it.preferenceInt == intValue } + } catch (e: Exception) { + throw IllegalStateException("Unknown play over notification setting: $stringValue") + } + } + } +} diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt index 1193e050b64..898132e172c 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt @@ -397,7 +397,7 @@ interface Settings { fun setPopularPodcastCountryCode(code: String) - fun getPlayOverNotification(): Int + fun getPlayOverNotification(): PlayOverNotificationSetting fun hasBlockAlreadyRun(label: String): Boolean fun setBlockAlreadyRun(label: String, hasRun: Boolean) diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt index b62546aa23c..f6c2f73534d 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt @@ -504,12 +504,12 @@ class SettingsImpl @Inject constructor( return getBoolean(Settings.PREFERENCE_AUTO_SHOW_PLAYED, false) } - override fun getPlayOverNotification(): Int { + override fun getPlayOverNotification(): PlayOverNotificationSetting { val value = sharedPreferences.getString( Settings.PREFERENCE_NOTIFICATION_AUDIO, Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT ) ?: Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT - return Integer.parseInt(value) + return PlayOverNotificationSetting.fromPreferenceString(value) } override fun hasBlockAlreadyRun(label: String): Boolean { diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt index c1346e9e5b2..7d032c645a9 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt @@ -7,6 +7,7 @@ import android.media.AudioManager import androidx.media.AudioAttributesCompat import androidx.media.AudioFocusRequestCompat import androidx.media.AudioManagerCompat +import au.com.shiftyjelly.pocketcasts.preferences.PlayOverNotificationSetting import au.com.shiftyjelly.pocketcasts.preferences.Settings import au.com.shiftyjelly.pocketcasts.utils.log.LogBuffer import timber.log.Timber @@ -150,21 +151,10 @@ open class FocusManager(private val settings: Settings, context: Context?) : Aud } } - enum class PlayOverNotificationSetting { - NEVER, DUCK, ALWAYS - } - private fun canDuck(): PlayOverNotificationSetting { if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK_TRANSIENT) return PlayOverNotificationSetting.NEVER - return playOverNotification() + return settings.getPlayOverNotification() } - - protected open fun playOverNotification() = when (settings.getPlayOverNotification()) { - 0 -> PlayOverNotificationSetting.ALWAYS - 1 -> PlayOverNotificationSetting.DUCK - else -> PlayOverNotificationSetting.NEVER - } - interface FocusChangeListener { fun onFocusGain(shouldResume: Boolean) fun onFocusLoss(playOverNotification: PlayOverNotificationSetting, transientLoss: Boolean) diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt index d871706153e..021f6c1398a 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PlaybackManager.kt @@ -30,6 +30,7 @@ import au.com.shiftyjelly.pocketcasts.models.to.PodcastGrouping import au.com.shiftyjelly.pocketcasts.models.type.EpisodePlayingStatus import au.com.shiftyjelly.pocketcasts.models.type.EpisodeStatusEnum import au.com.shiftyjelly.pocketcasts.models.type.UserEpisodeServerStatus +import au.com.shiftyjelly.pocketcasts.preferences.PlayOverNotificationSetting import au.com.shiftyjelly.pocketcasts.preferences.Settings import au.com.shiftyjelly.pocketcasts.repositories.R import au.com.shiftyjelly.pocketcasts.repositories.chromecast.CastManager @@ -1337,14 +1338,14 @@ open class PlaybackManager @Inject constructor( focusWasPlaying = null } - override fun onFocusLoss(playOverNotification: FocusManager.PlayOverNotificationSetting, transientLoss: Boolean) { + override fun onFocusLoss(playOverNotification: PlayOverNotificationSetting, transientLoss: Boolean) { val player = player if (player == null || player.isRemote) { return } // if we are playing but can't just reduce the volume then play when focus gained val playing = isPlaying() - if ((playOverNotification == FocusManager.PlayOverNotificationSetting.NEVER) && playing) { + if ((playOverNotification == PlayOverNotificationSetting.NEVER) && playing) { LogBuffer.i(LogBuffer.TAG_PLAYBACK, "Focus lost while playing") focusWasPlaying = Date() @@ -1355,7 +1356,7 @@ open class PlaybackManager @Inject constructor( } // check if we need to reduce the volume - if (playOverNotification == FocusManager.PlayOverNotificationSetting.DUCK) { + if (playOverNotification == PlayOverNotificationSetting.DUCK) { player.setVolume(VOLUME_DUCK) return } diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt index 0130df69681..b7969378de3 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/support/Support.kt @@ -406,7 +406,7 @@ class Support @Inject constructor( output.append(eol) output.append("Notifications").append(eol) - output.append("Play over notifications? ").append(playOverNotificationString(settings.getPlayOverNotification())).append(eol) + output.append("Play over notifications? ").append(settings.getPlayOverNotification().analyticsString).append(eol) output.append("Hide notification on pause? ").append(if (settings.hideNotificationOnPause()) "yes" else "no").append(eol) output.append(eol) @@ -475,13 +475,6 @@ class Support @Inject constructor( return if (value) "yes" else "no" } - private fun playOverNotificationString(value: Int) = when (value) { - 0 -> "always" - 1 -> "duck" - 2 -> "never" - else -> "unknown" - } - private fun getDeviceName(): String { try { return DeviceName.getDeviceName() From bf20eaa790b4261d1ada67bbb67519df2143f1b3 Mon Sep 17 00:00:00 2001 From: Jamie McDowell Date: Sun, 16 Jul 2023 21:39:33 +0100 Subject: [PATCH 3/4] Audio ducking now reads legacy setting --- CHANGELOG.md | 5 +++-- .../settings/NotificationsSettingsFragment.kt | 4 ++-- .../src/main/res/xml/preferences_notifications.xml | 2 +- .../localization/src/main/res/values/strings.xml | 2 +- .../shiftyjelly/pocketcasts/preferences/Settings.kt | 4 ++-- .../pocketcasts/preferences/SettingsImpl.kt | 13 +++++++++---- .../repositories/playback/FocusManager.kt | 1 + 7 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ca1732e692..5618e0c1e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ * Added share option to episode swipe and multiselect menus ([#1190](https://github.com/Automattic/pocket-casts-android/pull/1190)), ([#1191](https://github.com/Automattic/pocket-casts-android/pull/1191)) +* Bug Fixes: + * Added audio ducking as an option when playing over notifications + ([#1009](https://github.com/Automattic/pocket-casts-android/pull/1009)). 7.43 ----- @@ -64,8 +67,6 @@ ([#973](https://github.com/Automattic/pocket-casts-android/pull/973)). * Improved the Automotive user profile view ([#975](https://github.com/Automattic/pocket-casts-android/pull/975)). - * Added audio ducking as an option when playing over external notifications - ([#1009](https://github.com/Automattic/pocket-casts-android/pull/1009)). 7.39 ----- diff --git a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt index 67197f4fb66..cedda73a6a4 100644 --- a/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt +++ b/modules/features/settings/src/main/java/au/com/shiftyjelly/pocketcasts/settings/NotificationsSettingsFragment.kt @@ -97,7 +97,7 @@ class NotificationsSettingsFragment : vibratePreference = manager.findPreference("notificationVibrate") notificationActions = manager.findPreference("notificationActions") systemSettingsPreference = manager.findPreference("openSystemSettings") - playOverNotificationPreference = manager.findPreference("notificationAudio") + playOverNotificationPreference = manager.findPreference("overrideNotificationAudio") // turn preferences off by default, because they are enable async, we don't want this view to remove them from the screen after it loads as it looks jarring enabledPreferences(false) @@ -410,7 +410,7 @@ class NotificationsSettingsFragment : override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) { if (Settings.PREFERENCE_NOTIFICATION_VIBRATE == key) { changeVibrateSummary() - } else if (Settings.PREFERENCE_NOTIFICATION_AUDIO == key) { + } else if (Settings.PREFERENCE_OVERRIDE_NOTIFICATION_AUDIO == key) { changePlayOverNotificationSummary() } } diff --git a/modules/features/settings/src/main/res/xml/preferences_notifications.xml b/modules/features/settings/src/main/res/xml/preferences_notifications.xml index 90b51bfd249..8355e0c24d6 100644 --- a/modules/features/settings/src/main/res/xml/preferences_notifications.xml +++ b/modules/features/settings/src/main/res/xml/preferences_notifications.xml @@ -43,7 +43,7 @@ diff --git a/modules/services/localization/src/main/res/values/strings.xml b/modules/services/localization/src/main/res/values/strings.xml index 35fd92b9c36..5e162689ea0 100644 --- a/modules/services/localization/src/main/res/values/strings.xml +++ b/modules/services/localization/src/main/res/values/strings.xml @@ -1135,7 +1135,7 @@ Choose podcasts Hide playback notification on pause Notify me - Play over external notifications + Play over notifications Never Duck volume Always diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt index 898132e172c..197cff2875e 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/Settings.kt @@ -83,8 +83,8 @@ interface Settings { const val PREFERENCE_SELECT_PODCAST_LIBRARY_SORT = "selectPodcastLibrarySort" const val PREFERENCE_WARN_WHEN_NOT_ON_WIFI = "warnWhenNotOnWifi" const val PREFERENCE_SYNC_ON_METERED = "SyncWhenOnMetered" - const val PREFERENCE_NOTIFICATION_AUDIO = "notificationAudio" - const val PREFERENCE_NOTIFICATION_AUDIO_DEFAULT = "2" + const val PREFERENCE_OVERRIDE_AUDIO_LEGACY = "overrideAudioInterruption" + const val PREFERENCE_OVERRIDE_NOTIFICATION_AUDIO = "overrideNotificationAudio" const val PREFERENCE_USE_EMBEDDED_ARTWORK = "useEmbeddedArtwork" const val PREFERENCE_LAST_MODIFIED = "lastModified" const val PREFERENCE_FIRST_SYNC_RUN = "firstSyncRun" diff --git a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt index f6c2f73534d..25f7bb5bd6c 100644 --- a/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt +++ b/modules/services/preferences/src/main/java/au/com/shiftyjelly/pocketcasts/preferences/SettingsImpl.kt @@ -505,13 +505,18 @@ class SettingsImpl @Inject constructor( } override fun getPlayOverNotification(): PlayOverNotificationSetting { - val value = sharedPreferences.getString( - Settings.PREFERENCE_NOTIFICATION_AUDIO, - Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT - ) ?: Settings.PREFERENCE_NOTIFICATION_AUDIO_DEFAULT + val value = sharedPreferences.getString(Settings.PREFERENCE_OVERRIDE_NOTIFICATION_AUDIO, null) ?: legacyPlayOverNotification() return PlayOverNotificationSetting.fromPreferenceString(value) } + private fun legacyPlayOverNotification(): String { + if (sharedPreferences.getBoolean(Settings.PREFERENCE_OVERRIDE_AUDIO_LEGACY, false)) { + return PlayOverNotificationSetting.ALWAYS.preferenceInt.toString() + } + + return PlayOverNotificationSetting.NEVER.preferenceInt.toString() + } + override fun hasBlockAlreadyRun(label: String): Boolean { return sharedPreferences.getBoolean("blockAlreadyRun$label", false) } diff --git a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt index 7d032c645a9..d48688452e8 100644 --- a/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt +++ b/modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/FocusManager.kt @@ -155,6 +155,7 @@ open class FocusManager(private val settings: Settings, context: Context?) : Aud if (audioFocus != AUDIO_NO_FOCUS_CAN_DUCK_TRANSIENT) return PlayOverNotificationSetting.NEVER return settings.getPlayOverNotification() } + interface FocusChangeListener { fun onFocusGain(shouldResume: Boolean) fun onFocusLoss(playOverNotification: PlayOverNotificationSetting, transientLoss: Boolean) From 9511f0a4c8bfe80c1224b329f78003735e33e7d5 Mon Sep 17 00:00:00 2001 From: Matt Chowning Date: Mon, 24 Jul 2023 15:52:15 -0400 Subject: [PATCH 4/4] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5618e0c1e34..057fcd142ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +7.45 +----- +* Bug Fixes: + * Added audio ducking as an option when playing over notifications + ([#1009](https://github.com/Automattic/pocket-casts-android/pull/1009)) + + 7.44 ----- * New Feature: @@ -8,9 +15,6 @@ * Added share option to episode swipe and multiselect menus ([#1190](https://github.com/Automattic/pocket-casts-android/pull/1190)), ([#1191](https://github.com/Automattic/pocket-casts-android/pull/1191)) -* Bug Fixes: - * Added audio ducking as an option when playing over notifications - ([#1009](https://github.com/Automattic/pocket-casts-android/pull/1009)). 7.43 -----