iOS Player - 933娱乐-放松心情精彩娱乐

一个音频播放器,要考虑的因素很多,首先这个播放器应该是一个单例,因为无论是哪个界面推出播放器,只能存在一个,存在就播放,不存在才能创建。先来看看效果图。


效果图

播放音频,首先会考虑到AVFoundation框架,这个是苹果专门给开发者用来播放音频的框架,本地和网络资源都可以播放。

AVPlayer:AVPlayer存在于AVFoundation中,其实它是一个视频播放器,但是用它来播放音乐是没问题的,本地音频和流媒体播放,但处理音频不够灵活;但是它对视屏有很高自由度的控制,而且能够自定义视屏播放界面。但是用来播放音频也是没有问题的。

AVPlayerItem:AVPlayerItem是一个载体,承载AVAsset,然后通过AVPlayer进行播放.我们要想对一个资源进行播放,那么就要通过AVPlayerItem和AVPlayerItemTrack来构建对应的动态内容

1、创建单例:用来承载播放器的控制器

+ (instancetype)sharedInstance{

static PlayerViewController *once_player = nil;

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

once_player = [[PlayerViewController alloc]init];

AVAudioSession *session = [AVAudioSession sharedInstance];[session setCategory:AVAudioSessionCategoryPlayback error:nil];//而且要激活,音频会话。

[session setActive:YES error:nil];//这段代码用来后台播放

});

return once_player;

}

1、创建palyer和服务

-(void)playCurrtnItem:(ShiCiDetialModel*)model{

self.model = model;

self.isPlay = YES;

self.isSXPlay = YES;

self.currtenLable.text = @"00:00:00";

self.dutionLable.text = model.duration;

self.progressView.progress = 0;

self.slider.value = 0;

[self removePlayLoadTime];

//移除监听音乐播放进度

[self removeTimeObserver];

[self removePlayStatus];

[self roatationAnimation];

[self setHeadviewImageBy:model];

if (self.player) {

//存在就播放

if (self.music_id == model.id) {

//id 相同直接播放(点击播放的时候)

[self.player play];

}else{

//不同的创建AVPlayerItem ,资源是在这里加载的

[self showBaseHudWithTitle:@""];

self.playItem = [[AVPlayerItem alloc]initWithURL:[NSURL URLWithString:model.playurl]];

[self.player replaceCurrentItemWithPlayerItem:self.playItem];//播放不同的,只需要替换掉AVPlayerItem就可以了

[self.player play];

}

}else{

//player不存在就创建

[self showBaseHudWithTitle:@""];

self.playItem = [[AVPlayerItem alloc]initWithURL:[NSURL URLWithString:model.playurl]];

self.player = [[AVPlayer alloc]initWithPlayerItem:self.playItem];

[self.player play];

}

self.music_id = model.id;

[self addNSNotificationForPlayMusicFinish];

//监听播放器状态

[self addPlayStatus];

//监听音乐缓冲进度

[self addPlayLoadTime];

//监听音乐播放的进度

[self addMusicProgressWithItem:self.player.currentItem];

}

2、各种状态的监听

-(void)addPlayStatus{       

[self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; 

  }/

/移除监听播放器状态

-(void)removePlayStatus{ 

  if (self.model == nil) {return;

}       

[self.player.currentItem removeObserver:self forKeyPath:@"status"];

}/

/KVO监听音乐缓冲状态

-(void)addPlayLoadTime{ 

  [self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];  

}

//移除监听音乐缓冲状态

-(void)removePlayLoadTime{   

if (self.model == nil) {return;

}   

[self.player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"];

}

#pragma mark - NSNotification

-(void)addNSNotificationForPlayMusicFinish{ 

      [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_player.currentItem];

}

-(void)playFinished:(NSNotification*)notification{  

[[NSNotificationCenter defaultCenter] removeObserver:self];     

  //播放下一首 

  [self nextOneClick:nil];

}

//监听音乐播放的进度

-(void)addMusicProgressWithItem:(AVPlayerItem *)item{ 

      __weak typeof(self) weakSelf = self;

  self.timeObserver =  [self.player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {     

  //当前播放的时间       

float current = CMTimeGetSeconds(time);      

//总时间       

float total = CMTimeGetSeconds(item.duration);     

  if (current) {           

float progress = current / total;          

//更新播放进度条          

weakSelf.slider.value = progress;          

weakSelf.currtenLable.text = [weakSelf timeFormatted:current];      

}    }];  

}

//转换成时分秒

- (NSString *)timeFormatted:(NSInteger)totalSeconds{   

NSInteger seconds = totalSeconds % 60;  

NSInteger minutes = (totalSeconds / 60) % 60;  

NSInteger hours = totalSeconds/3600;       

return [NSString stringWithFormat:@"%02ld:%02ld:%02ld",hours,minutes, seconds];}

//移除监听音乐播放进度

-(void)removeTimeObserver{ 

  if (self.timeObserver) {      

[self.player removeTimeObserver:self.timeObserver];   

    self.timeObserver = nil;    }}

//观察者回调

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context

{

if ([keyPath isEqualToString:@"status"]) {

switch (self.player.status) {

case AVPlayerStatusUnknown:

{

}

break;

case AVPlayerStatusReadyToPlay:

{

}

break;

case AVPlayerStatusFailed:

{

}

break;

default:

break;

}

}

if ([keyPath isEqualToString:@"loadedTimeRanges"]) {

NSArray * timeRanges = self.player.currentItem.loadedTimeRanges;

//本次缓冲的时间范围

CMTimeRange timeRange = [timeRanges.firstObject CMTimeRangeValue];

//缓冲总长度

NSTimeInterval totalLoadTime = CMTimeGetSeconds(timeRange.start) + CMTimeGetSeconds(timeRange.duration);

//音乐的总时间

NSTimeInterval duration = CMTimeGetSeconds(self.player.currentItem.duration);

//计算缓冲百分比例

NSTimeInterval scale = totalLoadTime/duration;

//更新缓冲进度条

self.progressView.progress = scale;

if (scale == 1) {

[self dismissHud];

}

}

}

3、上一曲下一曲和随机播放

-(void)lastOneClick:(UIButton*)button{

if (self.currtenflag==0) {

[self showWarningHudWithWarningTitle:@"前面没有了哟"];

[self dismissHudAfter:1.f];

}else{

self.currtenflag--;

self.model = self.modelArr[self.currtenflag];

[self playCurrtnItem:self.model];

}

}

-(void)playClick:(UIButton*)button{

if (self.isPlay) {

CALayer *presentLayer = (CALayer*)self.headView.layer.presentationLayer;

[self.headView.layer removeAnimationForKey:@"playAnimation"];

self.headView.layer.transform = presentLayer.transform;

[self.playBtn setImage:ECIMAGENAME(@"pasu") forState:UIControlStateNormal];

self.isPlay = NO;

self.model = nil;

[self.player pause];

}else{

[self roatationAnimation];

self.isPlay = YES;

[self.playBtn setImage:ECIMAGENAME(@"play") forState:UIControlStateNormal];

[self.player play];

}

}

-(void)nextOneClick:(UIButton*)button{

if (self.modelArr.count - self.currtenflag == 1||self.modelArr.count - self.currtenflag == 0) {

[self showWarningHudWithWarningTitle:@"后面没有了哟"];

[self dismissHudAfter:2.f];

CALayer *presentLayer = (CALayer*)self.headView.layer.presentationLayer;

[self.headView.layer removeAnimationForKey:@"playAnimation"];

self.headView.layer.transform = presentLayer.transform;

[self.playBtn setImage:ECIMAGENAME(@"pasu") forState:UIControlStateNormal];

self.isPlay = NO;

self.player = nil;

}else{

self.currtenflag++;

self.model = self.modelArr[self.currtenflag];

[self playCurrtnItem:self.model];

}

}

-(void)showListClick:(UIButton*)button{

if (self.modelArr.count) {

self.popView = [[ZYFPopview alloc]initView:self.view rows:self.modelArr defaultSelectRow:self.currtenflag selectDone:^(NSInteger selectRow) {

self.currtenflag = selectRow;

self.model = self.modelArr[selectRow];

[self playCurrtnItem:self.model];

} canleDone:^{

}];

[self.popView showPopView];

}else{

[self showBaseHud];

[self dismissHudWithWarningTitle:@"没有歌单" After:1.f];

}

}

-(void)playStyleClick:(UIButton*)button{

NSInteger playFlag = 0;

if (self.isSXPlay) {

//随机播放

NSInteger arrCount = self.modelArr.count;

playFlag = self.currtenflag;

self.currtenflag = arc4random()%(arrCount-1);

self.isSXPlay = NO;

[self.playStyleBtn setImage:ECIMAGENAME(@"suiji") forState:UIControlStateNormal];

}else{

//顺序播放

self.currtenflag = playFlag;

self.isSXPlay = YES;

[self.playStyleBtn setImage:ECIMAGENAME(@"shunxu") forState:UIControlStateNormal];

}

}

- (void)roatationAnimation{

//dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];

rotationAnimation.fromValue = @(0.0);

rotationAnimation.toValue  = @(M_PI*2);

rotationAnimation.duration  = 20;

rotationAnimation.repeatCount = HUGE_VAL;

[self.headView.layer addAnimation:rotationAnimation forKey:@"playAnimation"];

// });

}

里面的逻辑大概就是这样详情代码请到GitHub下载:

https://github.com/Dreamer929

你可能感兴趣的:(iOS Player - 933娱乐-放松心情精彩娱乐)