由于最近閑著沒事绪励,想找有關(guān)在線音樂(lè)播放的demo學(xué)習(xí)一下割疾,在gitHub跟code4APP上面查找了很多帖子却盘,結(jié)果很多在線音樂(lè)都是基于AudioStream實(shí)現(xiàn)的拴疤,我感覺用起來(lái)不太方便。后來(lái)突然發(fā)現(xiàn)字管,AVFoundation框架中提供了一個(gè)AVPlayer可以用來(lái)實(shí)現(xiàn)在線音樂(lè)播放啰挪,特地學(xué)習(xí)了一下,封裝成了SZKAVPlayer,與大家共享一下纤掸,筆者第一次寫這些功能文檔脐供,如果有不足或者錯(cuò)誤的地方,歡迎大家批評(píng)指正借跪。廢話不多說(shuō)政己,直接上調(diào)用的代碼:
在ViewController.m首先導(dǎo)入頭文件,并掛上SZKAVPlayerDelegate代理
#import "SZKAVPlayer.h"
準(zhǔn)備好相關(guān)的數(shù)據(jù)源
#pragma mark---歌曲名稱數(shù)組
-(NSArray *)songNameArr
{
_songNameArr=@[@"火星情報(bào)局 (《火星情報(bào)局》節(jié)目主題曲)",@"下一站我是你的依靠",@"世界上不存在的歌(《火鍋英雄》電影主題曲)"];
return _songNameArr;
}
#pragma mark---歌曲流媒體地址
-(NSArray *)songArr
{
_songArr=@[@"http://ws.stream.qqmusic.qq.com/105857360.m4a?fromtag=46",@"http://ws.stream.qqmusic.qq.com/105772207.m4a?fromtag=46",@"http://ws.stream.qqmusic.qq.com/105857409.m4a?fromtag=46"];
return _songArr;
}
#pragma mark---歌曲演唱者數(shù)組
-(NSArray *)songAuthorArr
{
_songAuthorArr=@[@"華晨宇",@"金志文",@"趙英俊"];
return _songAuthorArr;
}
#pragma mark---歌曲圖片的數(shù)組
-(NSArray *)songImageArr
{
_songImageArr=@[@"http://i.gtimg.cn/music/photo/mid_album_300/W/8/003re5702kSBW8.jpg",@"http://i.gtimg.cn/music/photo/mid_album_300/z/9/002PnERL0JwJz9.jpg",@"photo3.jpg"];
return _songImageArr;
}
初始化player時(shí)傳入歌曲的網(wǎng)址數(shù)組跟歌曲的背景圖片數(shù)組便可實(shí)現(xiàn)當(dāng)前歌曲播放結(jié)束后,自動(dòng)播放下一首并切換player的背景圖片(支持本地圖片和網(wǎng)絡(luò)圖片)
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor=[UIColor colorWithWhite:0.875 alpha:1.000];
//添加playerView
[self addPlayerView];
}
#pragma mark---添加playerView
-(void)addPlayerView
{
_player=[[SZKAVPlayer alloc]initWithFrame:CGRectMake(WIDTH/4, HEIGHT/2-WIDTH/4, WIDTH/2, WIDTH/2) andSongUrlArr:self.songArr andSongImageArr:self.songImageArr];
_player.delegate=self;
_player.layer.cornerRadius=WIDTH/4;
_player.layer.masksToBounds=YES;
_player.backgroundColor=[UIColor yellowColor];
//設(shè)置volume掏愁,不設(shè)置默認(rèn)為0.5
_player.volume=0.8;
[self.view addSubview:_player];
}
實(shí)現(xiàn)代理方法可自動(dòng)返回當(dāng)前時(shí)間歇由,總共時(shí)間,歌曲進(jìn)度以及點(diǎn)擊次數(shù)果港,并且時(shí)間的格式已經(jīng)轉(zhuǎn)換成00:00的格式
#pragma mark----SZKAVPlayerDelegate代理方法
-(void)getSongCurrentTime:(NSString *)currentTime andTotalTime:(NSString *)totalTime andProgress:(CGFloat)progress andTapCount:(NSInteger)tapCount
{
//進(jìn)度條
[_progressView setProgress:progress];
//歌曲時(shí)間
_songTime.text=[NSString stringWithFormat:@"%@/%@",currentTime,totalTime];
//歌曲名稱
_songName.text=self.songNameArr[tapCount];
//歌曲演唱者
_songAuthor.text=self.songAuthorArr[tapCount];
}
player的其他操作調(diào)用SZKAVPlayer.h中相關(guān)的API即可
/**
* 開始播放
*/
-(void)startPlay;
/**
* 暫停播放
*/
-(void)puasePlay;
/**
* 播放下一首
*/
-(void)nextSong;
/**
* 播放上一首
*/
-(void)lastSong;
最終效果圖:
SZKAVPlayer的調(diào)用方法大致就是這樣沦泌,只需要在初始化時(shí)傳入歌曲數(shù)組和歌曲圖片,便可實(shí)現(xiàn)當(dāng)前歌曲結(jié)束后辛掠,自動(dòng)播放下一首谢谦,同時(shí)切換歌曲圖片,并且代理方法中的歌曲的當(dāng)前時(shí)間萝衩,總共時(shí)間以及播放進(jìn)度回挽,也會(huì)隨著歌曲的切換而自動(dòng)刷新。
下面大致介紹一下SZKAVPlayer.m的實(shí)現(xiàn)方法
songItem和player用來(lái)初始化SZKAVPlayer
//初始化songItem和player
_songItem=[AVPlayerItem playerItemWithURL:url];
_player=[AVPlayer playerWithPlayerItem:_songItem];
[_player play];
并對(duì)播放器添加了三個(gè)監(jiān)聽和一個(gè)通知
#pragma mark----監(jiān)聽播放器的加載狀態(tài)
-(void)addAVPlayerStatusObserver
{
[_songItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
}
#pragma mark----數(shù)據(jù)緩沖狀態(tài)的監(jiān)聽
-(void)addNetDataStatusObserver
{
[_songItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
#pragma mark----添加觀察者監(jiān)聽獲取當(dāng)前時(shí)間,總共時(shí)間,進(jìn)度
-(void)addTimeObserve
{
__block AVPlayerItem *songItem=_songItem;
__block typeof(self) bself = self;
_timeObserver=[_player addPeriodicTimeObserverForInterval:CMTimeMake(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
//設(shè)置player的聲音
[bself setPlayerVolume];
//添加背景圖片
NSString *imagrStr=bself.imageArr[bself.tapCount];
if (imagrStr.length<=4) {
bself.playerImage.image=[UIImage imageNamed:bself.imageArr[bself.tapCount]];
}else{
NSString *imagrSubStr=[imagrStr substringWithRange:NSMakeRange(0, 4)];
if ([imagrSubStr isEqualToString:@"http"]) {
NSURL *imageUrl=[NSURL URLWithString:bself.imageArr[bself.tapCount]];
[bself.playerImage setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:@"radioBG"]];
}else{
bself.playerImage.image=[UIImage imageNamed:bself.imageArr[bself.tapCount]];
}
}
//當(dāng)前時(shí)間
float current=CMTimeGetSeconds(time);
//總共時(shí)間
float total=CMTimeGetSeconds(songItem.duration);
//進(jìn)度
float progress=current/total;
//將值傳入知道delegate方法中
[bself.delegate getSongCurrentTime:[bself formatTime:current] andTotalTime:[bself formatTime:total] andProgress:progress andTapCount:bself.tapCount];
}];
}
#pragma mark----播放完成后發(fā)送通知
-(void)addPlayToEndObserver
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_songItem];
}
為了防止在進(jìn)行下一首歌曲時(shí)候監(jiān)聽出錯(cuò)猩谊,在當(dāng)前歌曲結(jié)束后移除所有監(jiān)聽千劈,在下一首歌曲播放前再次添加監(jiān)聽,筆者親測(cè)目前這樣寫沒有出現(xiàn)什么問(wèn)題牌捷。
大致的功能原理先寫到這墙牌,筆者第一次寫涡驮,不足的地方還望各位讀者見諒,如果遇到什么問(wèn)題喜滨,可以評(píng)論回復(fù)捉捅,筆者收到后第一時(shí)間回復(fù)大家,也可以添加筆者的QQ/微信:790057066 鸿市,并且剛剛把demo上傳到了GitHub上面感興趣的朋友锯梁,可以上去下載查看即碗,記得star下焰情,非常感謝。
SZKAVPlayer鏈接 https://github.com/18811314750/SZKAVPlayer
筆者的其他文章
iOS開發(fā)-利用命令行實(shí)現(xiàn)將本地代碼上傳到GitHub
http://www.reibang.com/p/79b94add9057
iOS開發(fā)-快速調(diào)用照相機(jī)和相冊(cè)剥懒,并實(shí)現(xiàn)沙盒中照片的保存與讀取
http://www.reibang.com/p/7ffc8844e956