前言
最近在做项目的时候需要用到一个在线的音乐播放器, 但是这个音乐播放器只需要播放一首歌, 而且要求能快进快退, 由于比较简单, 适合初学者学习, 所以我特意封装了一下, 并写了一个小小的demo, 代码都在github上, 众多iOS学习爱好者有兴趣的话可以前往下载. github地址
特点
- 体量小
- 简单易用
- 支持单首歌曲的播放,快进,快退
- 支持播放进度条的拖动以及点击
使用方法
- 下载并复制KHPlayer文件夹下的源代码到你的工程目录
- 注意:如果想使用原资源图片, 一定要把Assets里的图片一起复制过去
- 初始化KHPlayer, 赋值Frame, 并添加到当前视图中
KHPlayer *player = [[KHPlayer alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.view.frame) - 70, CGRectGetWidth(self.view.frame),70)];
[self.view addSubview:player];
- 设置相关的UI属性
[player setSliderThumbImage:[UIImage imageNamed:@"yinpinThumb"]];
[player enableMasksToBoundsOfSlider];
[player setBgColor:[UIColor whiteColor]];
- 设置要播放的在线音频URL的String值, 并调用
play
方法进行播放
[player setURLString: kInterface1];
[player play];
完成以上操作后得到的效果如下:
后续工作
- 添加播放本地音频的接口
- 添加连续播放多首歌的功能
核心代码
其实最核心的代码是给播放器添加KVO监听事件, 所以在这里只展示这部分代码
//添加在线播放的音频URL
- (void)setURLString:(NSString *)urlString{
_urlString = urlString;
if (self.currentItem) {
[self.currentItem removeObserver:self forKeyPath:@"status"];
[self.currentItem removeObserver:self forKeyPath:@"playbackBufferEmpty"];
[self.currentItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"];
self.currentItem = nil;
}
if (self.player) {
self.player = nil;
}
if (self.progressSlider) {
self.progressSlider.value = 0;
}
//给playerItem添加KVO事件
self.currentItem = [[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:urlString]];
[self.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
[self.currentItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil];
[self.currentItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil];
self.player = [[AVPlayer alloc] initWithPlayerItem:self.currentItem];
}
/*
使用KVO监听播放状态
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"status"])
{
//准备播放
if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusReadyToPlay)
{
self.duration = CMTimeGetSeconds(self.currentItem.duration);
self.rightTimeLabel.text = [self timeFormatWithTimtInterval:_duration];
[self updatePlayerProgress];
[self hideLoadingView];
[self enableButtons];
}
else if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusFailed)
{
[self showLoadingView];
[self disableButtons];
NSLog(@"播放失败");
}
else if ([change[NSKeyValueChangeNewKey] integerValue] == AVPlayerItemStatusUnknown)
{
[self showLoadingView];
[self disableButtons];
NSLog(@"未知错误");
}
}
else if ([keyPath isEqualToString:@"playbackBufferEmpty"])
{
if (self.currentItem.playbackBufferEmpty) {
[self showLoadingView];
self.progressSlider.value = 0;
[self disableButtons];
}
}
else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"])
{
[self showLoadingView];
if (self.currentItem.playbackLikelyToKeepUp) {
[self hideLoadingView];
[self enableButtons];
}
}
}
/*
设置定时器,更新播放状态
*/
- (void)updatePlayerProgress{
__weak typeof(self) weakSelf = self;
[_player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.5, NSEC_PER_SEC) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
//更新左右的时间Label, 修改进度条进度(这里要用weakSelf来防止循环引用)
CGFloat currentTime = CMTimeGetSeconds(weakSelf.currentItem.currentTime);
weakSelf.currentTime = currentTime;
weakSelf.leftTimeLabel.text = [weakSelf timeFormatWithTimtInterval:currentTime];
CGFloat leftTime = weakSelf.duration - currentTime;
weakSelf.rightTimeLabel.text = [weakSelf timeFormatWithTimtInterval:leftTime];
weakSelf.progressSlider.value = currentTime / weakSelf.duration;
}];
}
写在结尾的话
有兴趣了解所有代码和Demo的朋友, 还是那句话, 可以去我github地址下载. 觉得还不错的话不妨给我点个星哈~最后, 如果觉得代码哪里有问题,或者有新的的需求想添加上去,欢迎留下你的评论.
网友评论