So i am looking for a way to change current system volume (volume played from other apps like YouTube Music or Spotify) but gradually, so that the user is not surprised with a sudden volume change.
I tried this :
import MediaPlayer
func changeVolume(volume: Float) async{
do{
try! AVAudioSession.sharedInstance().setActive(true)
}
var currentvol = AVAudioSession.sharedInstance().outputVolume
let delta = volume - currentvol
var incrementer = currentvol/10*delta
print("--------------")
print("Volume : \(volume)")
print("currentvol : \(currentvol)")
print("incrementer : \(incrementer)")
print("delta : \(delta)")
while(currentvol < volume){
if(incrementer <= 0){
incrementer = 0.01
}
currentvol = incrementer
print("updated : \(currentvol)")
await MPVolumeView.setVolume(currentvol)
try! await Task.sleep(nanoseconds: UInt64(0.05 * Double(NSEC_PER_SEC)))
}
await MPVolumeView.setVolume(volume)
}
But the problem is that it pause the current music instead of just changing the volume (maybe because my app is taking over the mediaplayer i think)
My app do not play music so i'm just looking for a way to change volume from other apps while the user is using my app
Any idea how i could do ?
Thanks
CodePudding user response:
Note that while what you're describing is likely possible (I've shipped a product that does this in order to interoperate with custom hardware), it's completely unsupported, is likely to break in the future (it broke a couple of times for me when the OS upgraded), and can potentially get your app removed from AppStore. Given the changes we've seen in recent releases, I expect the tricks used to pull this off won't work at all in future OS versions. The feature you're describing is not permitted by Apple. As the docs for AVAudioSession.outputVolume
note: "Only the user can directly set the system volume. Provide a volume control in your app, using MPVolumeView, to provide the interface to adjust the system volume."
There is no MPVolumeView.setVolume
method in the public API, so it's unclear what you're actually doing here. You should likely include the code for the extension I assume you've written.
That said, the reason it's pausing is because you told it to pause here:
try! AVAudioSession.sharedInstance().setActive(true)
The default behavior of this line is to take control of the audio session in .playback
mode, which will interrupt all background sessions. Ideally you should not activate the audio session at all if you don't plan to play audio. If you do, then you should set the category to .ambient
(to indicate that audio is not important for your app) or you should pass the option .mixWithOthers
(to indicate it is important, but you still want other sessions to continue playing).
Depending on your actual goals, a better solution to this is likely to pass the option .duckOthers
, which will reduce the volume of other apps in a supported way.