AVPlayer切换播放源与循环播放
踩坑完毕:稍微总结一下使用方式:
第一步:把播放器做成一个单利类,方便外部的调用;毕竟一个APP一般同时就播放一个视频:+ +(VGVideoPlayer *)shareVGVideoPlayer{
static VGVideoPlayer *videoPlayer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
videoPlayer = [[VGVideoPlayer alloc] init];
[videoPlayer addNotification];
});
return videoPlayer;
}
第二步:拿到外部的数据,进行处理,当然了,你如果不是这样的数据,就可以不用看这个方法喽:
- (void)playVideoWithVideoModel:(VideoModel *_Nullable)model view:(UIView *_Nullable)view{
NSArray *movieSource = [model.source componentsSeparatedByString:@"."];
NSString *path = [[NSBundle mainBundle] pathForResource:movieSource[0] ofType:movieSource[1]];
if (movieId != [model.sourceId integerValue]) {
movieId = [model.sourceId integerValue];
self.loop = model.loop;
[self playWithUrlString:path view:view];
}
}
第三步:初始化:
- (void)playWithUrlString:(NSString *)urlString view:(UIView *)view{
if (urlString == nil) {
return;
}
[self creatBaseView:view];
if (self.player) {
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
}
NSURL *sourceUrl = [NSURL fileURLWithPath:urlString];
AVAsset *movieAsset = [AVAsset assetWithURL:sourceUrl];
[movieAsset loadValuesAsynchronouslyForKeys:@[@"duration", @"tracks", @"commonMetadata"] completionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
AVPlayerItem *playerItyem = [AVPlayerItem playerItemWithAsset:movieAsset];
if (!self.player) {
self.player = [AVPlayer playerWithPlayerItem:playerItyem];
[self.player setActionAtItemEnd:AVPlayerActionAtItemEndPause];
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player];
playerLayer.frame = CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT);
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
[self.baseView.layer addSublayer:playerLayer];
}else{
//切换播放源,解决闪屏问题
[self.player replaceCurrentItemWithPlayerItem:playerItyem];
}
//注册通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(runLoopTheMovie:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
[self.player play];
});
}];
}
- (void)creatBaseView:(UIView *)view{
if (!self.baseView) {
self.baseView = [[UIView alloc] initWithFrame:view.bounds];
[view addSubview:_baseView];
}
}
- (void)runLoopTheMovie:(NSNotification *)n{
if (![[n object] isEqual:self.player.currentItem]) {
return;
}
if (self.loop) {
//注册的通知 可以自动把 AVPlayerItem 对象传过来,只要接收一下就OK
AVPlayerItem * p = [n object];
//关键代码
[p seekToTime:kCMTimeZero];
[self.player play];
}else{
if (self.delegate && [self.delegate respondsToSelector:@selector(videoPlayEnd)]) {
[self.delegate videoPlayEnd];
}
}
}
解释一下字段:loop :视频是否可以循环播放;
- (void)stopPlaying{
[self.player pause];
self.player = nil;
movieId = 0;
[self.baseView removeFromSuperview];
self.baseView = nil;
}
#pragma mark - 添加挂起通知和进入前后台通知
-(void)addNotification{
// 后台&前台通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(becomeActiveNotification) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resignActiveNotification) name:UIApplicationWillResignActiveNotification object:nil];
}
// 挂起
- (void)resignActiveNotification{
if (self.player) {
[self.player pause];
time = self.player.currentTime;
}
positionImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, IPHONE_WIDTH, IPHONE_HEIGHT)];
positionImage.image = [self captureCurrentScreen];
[[[UIApplication sharedApplication] keyWindow] addSubview:positionImage];
}
// 结束挂起
- (void)becomeActiveNotification{
if (self.player) {
@try {
[self.player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
if (finished) {
[self.player play];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[positionImage removeFromSuperview];
positionImage = nil;
});
}
}];
} @catch (NSException *exception) {
[self.player play];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[positionImage removeFromSuperview];
positionImage = nil;
});
}
}
}
#pragma mark - 截取当前屏幕
- (UIImage *)captureCurrentScreen{
UIGraphicsBeginImageContextWithOptions(CGSizeMake(CGRectGetWidth(_baseView.frame), CGRectGetHeight(_baseView.frame)), NO, [UIScreen mainScreen].scale);
[_baseView drawViewHierarchyInRect:CGRectMake(0, 0, CGRectGetWidth(_baseView.frame), CGRectGetHeight(_baseView.frame)) afterScreenUpdates:NO];
UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return snapshot;
}
代码粘贴完毕:大家可以直接拷贝使用:完整的样式,下边截屏: