ambientlight
ambientlight

Reputation: 7332

iOS: Airplay picker MPVolumeView alternative

I'm using MPVolumeView to pick airplay device for avplayer airplay playback. Is there any possible non-private API alternative for doing this, so I would be able to provide my own UI Controls for picking airplay device?

By referring to the API, I mean, that all I need is:

  1. Ability to reroute audio to airplay-device specific audioRoute.
  2. Retrive airplay-device names. (get all available audioRoutes, then get descriptions for airplay audioRoutes)

I know AudioToolbox framework provides some additional API to deal AudioSession, but the only way I found to reroute audio is AVAudioSession's:

- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride  error:(NSError **)outError`

which only allows to reroute audio to build-in speakers. Maybe there is some other way how to achieve it there? (I also did only found the way how to retrieve the name of AirplayDevice as a description of the currentAudioRoute - Get name of AirPlay device using AVPlayer)

Upvotes: 4

Views: 3432

Answers (2)

malex
malex

Reputation: 10096

One should use AVRoutePickerView to manage all audio outputs

For instance, one can make subclass as follows

final class AMRoutePickerView: AVRoutePickerView {
    override init(frame: CGRect) {
        super.init(frame: frame)
        translatesAutoresizingMaskIntoConstraints = false
        tintColor = .clear
        activeTintColor = .clear
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Here we hide visual content of this view by setting .clear. Now one can put this view as top subview of any view or button from touchable UI.

Upvotes: 1

ambientlight
ambientlight

Reputation: 7332

So the precise answer to my question:

(i) It's not possible to switch audioRoutes programatically with public API except switching to build-in speakers.

[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];

(ii) You can only retrieve a name of airplay-device if it's active AudioRoute. Get name of AirPlay device using AVPlayer

So the practical solution to presenting customised UI Controls for selecting airplay would be:

To customise MPVolumeView, where you can disable volumeSliderand customise routeButton. However you have no other option as picking airplayDevice among list of apple-compatible wireless devices (airPlay, bluetooth, etc) in UIActionSheet that pop ups when you tap on routeButton, but you can observe when user will make a selection there by subscribing to audioRouteChangeNotification:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteHasChangedNotification:) name:AVAudioSessionRouteChangeNotification object:[AVAudioSession sharedInstance]];

(also note that if you will plug in/out headphones, it also will trigger this notification)

If you are interested how to retrieve all available audioRoutes and switch programmatically with private API:

MPMediaPlayer framework contains a private class MPAVRoutingController, which allows you exactly that:

Class MPAVRoutingController = NSClassFromString(@"MPAVRoutingController");
Class MPAVRoute = NSClassFromString(@"MPAVRoute");

id routingController = [[MPAVRoutingController alloc] init];
NSArray* availableRoutes = [routingController performSelector:@selector(availableRoutes)];
BOOL isSwitchSuccesful = [[routingController performSelector:@selector(pickRoute:) withObject:availableRoutes.lastObject] boolValue];

(if you want to then access audioRoute info and check if it is Airplay: Detecting airplayRoute)

Upvotes: 6

Related Questions