Template:iOS Airplay
From Engineering Client Portal
AirPlay
To implement OTT measurement, report OTT changes to the SDK using public API interface: updateOTT
In order to detect AirPlay and mirroring changes we use AVAudioSessionPortDescription properties that are different on different iOS versions. We found that on iOS versions 8 - 10 AVAudioSessionPortDescription
has the following values:
AirPlay: type = AirPlay; name = Apple TV 4K; UID = DC:56:E7:53:72:85-airplay
Mirroring: type = AirPlay; name = Apple TV 4K; UID = DC:56:E7:53:72:85-screen
For iOS 11+ some parameters like name and UID have different values:
AirPlay: type = AirPlay; name = AirPlay; UID = 0eb63aae-5915-45f1-b0f7-0102a0e50d53
Mirroring: type = AirPlay; name = Apple TV 4K; UID = 4335E8A9-1C0A-4251-9000-28CA5FA2F3CF-192731714653291-screen
The following code snipped is suggested for AirPlay / mirroring detection on iOS devices.
Swift
nielsenSdk.updateOTT(currentStatus)
Subscribe to AVAudioSessionRouteChangeNotification
NotificationCenter.default.addObserver(self, selector: #selector(handleRouteChanged(_:)), name: NSNotification.Name.AVAudioSessionRouteChange, object: nil)
Handle AVAudioSessionRouteChangeNotification and prepare OTT dictionary:
func handleRouteChanged(_ notification: Notification) {
var currentStatus: [String: String] = ["ottStatus": "0"]
let session = AVAudioSession.sharedInstance()
let currentRoute = session.currentRoute
for outputPort in currentRoute.outputs {
if outputPort.portType == AVAudioSessionPortAirPlay {
currentStatus["ottStatus"] = "1"
currentStatus["ottDeviceModel"] = outputPort.portName
currentStatus["ottDeviceID"] = outputPort.uid
if outputPort.portName == "AirPlay" {
currentStatus["ottDevice"] = "airplay"
currentStatus["ottType"] = "airplay"
}
else {
if outputPort.portName.contains("Apple TV") {
currentStatus["ottDevice"] = "appleTV"
}
else {
currentStatus["ottDevice"] = "other"
}
if outputPort.uid.hasSuffix("airplay") {
currentStatus["ottType"] = "airplay"
}
else if outputPort.uid.hasSuffix("screen") {
currentStatus["ottType"] = "mirroring"
}
else {
currentStatus["ottType"] = "other"
}
}
}
}
// report OTT status update to Nielsen SDK
self.reportOTTUpdate(currentStatus)
}
Report OTT update to the Nielsen SDK
func reportOTTUpdate(_ ottDict: [String: String]) {
if let nielsenSdk = self.nielsenAppApi {
nielsenSdk.updateOTT(currentStatus)
}
}
Objective C
– (void)updateOTT:(id)ottInfo;
Subscribe to AVAudioSessionRouteChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChanged:) name:AVAudioSessionRouteChangeNotification object:nil];
Handle AVAudioSessionRouteChangeNotification and prepare OTT dictionary:
- (void)handleRouteChanged:(NSNotification *)notification
{
NSMutableDictionary *ottDict = [NSMutableDictionary dictionaryWithDictionary: @{@"ottStatus": @"0"}];
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
AVAudioSessionRouteDescription *currentRoute = audioSession.currentRoute;
for (AVAudioSessionPortDescription *outputPort in currentRoute.outputs) {
if ([outputPort.portType isEqualToString:AVAudioSessionPortAirPlay]) {
ottDict[@"ottStatus"] = @"1";
ottDict[@"ottDeviceModel"] = outputPort.portName;
ottDict[@"ottDeviceID"] = outputPort.UID;
if ([outputPort.portName isEqualToString:@"AirPlay"]) {
ottDict[@"ottDevice"] = @"airplay";
ottDict[@"ottType"] = @"airplay";
}
else {
if ([outputPort.portName containsString:@"Apple TV"]) {
ottDict[@"ottDevice"] = @"appleTV";
}
else {
ottDict[@"ottDevice"] = @"other";
}
if ([outputPort.UID hasSuffix:@"airplay"]) {
ottDict[@"ottType"] = @"airplay";
}
else if ([outputPort.UID hasSuffix:@"screen"]) {
ottDict[@"ottType"] = @"mirroring";
}
else {
ottDict[@"ottType"] = @"other";
}
}
}
}
// report OTT status update to Nielsen SDK
[self reportOTTWithDict:ottDict];
}
Report OTT update to the Nielsen SDK
- (void)reportOTTWithDict:(NSDictionary *)ottDict
{
[self.nielsenSDK updateOTT:ottDict];
}