Disconnect from AirPlay device programmatically

Hello there, I'm trying to implement feature which uses AirPlay with Apple TV. I want to disconnect from the device programmatically when something happens. Under something I mean a situation when a user wants to stop broadcasting (for example close the PiP window on his phone). I use this snippet:

try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)

It works fine sometimes but not always (it works on iOS 18 but it doesn't on iOS 17 or ). So I thought it's a bug and create a ticker to feedback assistant (FB21220013). The support told me write a post on the forum.

Answered by DTS Engineer in 869575022

Hello @erawq,

There is no reliable way to disconnect your app's audio playback from an AirPlay route (aside from the user taking action to change the route in Control Center for example).

From AVAudioSessionTypes.h:

"- AVAudioSessionCategoryPlayAndRecord: /// DefaultToSpeaker will default to false, but >can be set to true, routing to Speaker /// (instead of Receiver) when no other audio route is connected."

The key phrasing here is "(instead of Receiver) when no other audio route is connected."

In other words:

try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)

This call is only expected to have an effect when audio is currently being routed to the device's receiver (the speaker which on most devices is at the top near the front-facing camera). In your case, audio is being routed to an AirPlay route, so it is expected that this call should not have an effect.

If you would like the capability of programmatically disconnecting from an AirPlay route, I suggest that you open a new Feedback to file that enhancement request.

Otherwise, my recommendation is that you do the following:

Under something I mean a situation when a user wants to stop broadcasting (for example close the PiP window on his phone).

When the user takes that action, if you detect a non-builtIn output for the currentRoute, you can present an AVRoutePickerView to the user, and then they can specify where they would like to route the audio to.

--Greg

Hello @erawq,

There is no reliable way to disconnect your app's audio playback from an AirPlay route (aside from the user taking action to change the route in Control Center for example).

From AVAudioSessionTypes.h:

"- AVAudioSessionCategoryPlayAndRecord: /// DefaultToSpeaker will default to false, but >can be set to true, routing to Speaker /// (instead of Receiver) when no other audio route is connected."

The key phrasing here is "(instead of Receiver) when no other audio route is connected."

In other words:

try audioSession.setCategory(.playAndRecord, options: .defaultToSpeaker)

This call is only expected to have an effect when audio is currently being routed to the device's receiver (the speaker which on most devices is at the top near the front-facing camera). In your case, audio is being routed to an AirPlay route, so it is expected that this call should not have an effect.

If you would like the capability of programmatically disconnecting from an AirPlay route, I suggest that you open a new Feedback to file that enhancement request.

Otherwise, my recommendation is that you do the following:

Under something I mean a situation when a user wants to stop broadcasting (for example close the PiP window on his phone).

When the user takes that action, if you detect a non-builtIn output for the currentRoute, you can present an AVRoutePickerView to the user, and then they can specify where they would like to route the audio to.

--Greg

Hello @DTS Engineer !

I would like to add that there is another, maybe related, issue. When a user uses AirPlay to stream a video from another app and opens video in my app, which is intended to play only on device - everything works as expected. But when a user opens a video in my app, which is allowed to be played through AirPlay, plays it on external screen, than closes a video, but does not disconnect AirPlay, and opens another screen where plays a video, that should stay on device, audio of that video starts to play through AirPlay. The same situation when there are 2 players on the second screen, where one plays video without audio and the other plays only audio. Player with only audio starts playback on external screen. I wonder if there is a way to signal to AVPlayer to stop trying to use AirPlay for other players, because ‘allowsExternalPlayback = false’ does not work and audio still tries to play through AirPlay. Thank you!

Disconnect from AirPlay device programmatically
 
 
Q