I am using Apple Airplay and AVPlayer
to show a video on an external display, while showing some controls on the device using Apple TV and AirPlay.
I am using this class to display the AVPlayer
on the external screen:
#import "AirPlayViewController.h"
@interface AirPlayViewController ()
@end
@implementation AirPlayViewController
- (id)initWithFrame:(CGRect)iFrame{
self.view.frame = iFrame;
self.backGroundImageView = [[UIImageView alloc]initWithFrame:iFrame];
[self.view addSubview: self.backGroundImageView];
return self;
}
- (void)viewDidLoad{
[super viewDidLoad];
}
-(void)viewWillDisappear:(BOOL)animated{
[audioVideoPlayer pause];
}
-(void)playMediaWithURL:(NSURL*)aURL{
audioVideoPlayer = [AVPlayer playerWithURL:aURL];
audioVideoPlayer.usesExternalPlaybackWhileExternalScreenIsActive=YES;
audioVideoPlayer.allowsExternalPlayback= YES;
//manually resizing and adding the layer, so that the app does not get confused with airplayfunctionality
AVPlayerLayer* playerLayer = [AVPlayerLayer playerLayerWithPlayer: audioVideoPlayer];
playerLayer.frame = self.view.bounds;
[self.view.layer addSublayer:playerLayer];
if (audioVideoPlayer) {
[audioVideoPlayer play];
}
}
-(void)stopMediaPlayback{
[audioVideoPlayer pause];
[[AVPlayerLayer playerLayerWithPlayer: audioVideoPlayer] removeFromSuperlayer];
audioVideoPlayer = nil;
}
@end
The problem I have is right there in playMediaWithURL:
. The AVPlayer
layer is not automatically added to the external screen but I have to add it by hand, which feels kind of dirty and leads to all kind of clean-up work when I want to remove the AVPlayer
from the view again.
Has anyone else had trouble with this and found some neat way to implement it?
The airPlayViewController
is called from another UIViewController
that contains the second window along with all the AirPlay delegate stuff to display it, using this function:
- (void)setupMirroringForScreen:(UIScreen *)anExternalScreen{
//find the correct resolution for the external screen
UIScreen *tScreen= anExternalScreen;
CGSize max = {0, 0};
UIScreenMode *maxScreenMode = nil;
for (UIScreenMode *current in tScreen.availableModes) {
if (maxScreenMode == nil || current.size.height > max.height || current.size.width > max.width) {
max = current.size;
maxScreenMode = current;
}
}
tScreen.currentMode = maxScreenMode;
// Setup window in external screen
self.externalWindow = [[UIWindow alloc] initWithFrame:tScreen.bounds];
self.externalWindow.hidden = NO;
self.externalWindow.layer.contentsGravity = kCAGravityResizeAspect;
self.externalWindow.screen = tScreen;
self.airPlayVC = [[AirPlayViewController alloc]initWithFrame:tScreen.bounds];
[self.airPlayVC.backGroundImageView setImage:[UIImage imageNamed:mainMenuExternalBackgroundImage]];
//try to play a video on the external Screen/ Audio file as fallback
NSURL *tURL= [[NSBundle mainBundle]URLForResource:mainMenuVideo withExtension:nil];
if (!tURL) {
tURL = [[NSBundle mainBundle] URLForResource:mainMenuAmbienceMusic withExtension:nil];
}
[self.airPlayVC playMediaWithURL:tURL];
[self.externalWindow addSubview:self.airPlayVC.view];
}