由于最近閑著沒事,想找有關在線音樂播放的demo學習一下,在gitHub跟code4APP上面查找了很多帖子,結果很多在線音樂都是基于AudioStream實現的,我感覺用起來不太方便。后來突然發現,AVFoundation框架中提供了一個AVPlayer可以用來實現在線音樂播放,特地學習了一下,封裝成了SZKAVPlayer,與大家共享一下,筆者第一次寫這些功能文檔,如果有不足或者錯誤的地方,歡迎大家批評指正。廢話不多說,直接上調用的代碼:
在ViewController.m首先導入頭文件,并掛上SZKAVPlayerDelegate代理
#import "SZKAVPlayer.h"
準備好相關的數據源
#pragma mark---歌曲名稱數組
-(NSArray *)songNameArr
{
_songNameArr=@[@"火星情報局 (《火星情報局》節目主題曲)",@"下一站我是你的依靠",@"世界上不存在的歌(《火鍋英雄》電影主題曲)"];
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---歌曲演唱者數組
-(NSArray *)songAuthorArr
{
_songAuthorArr=@[@"華晨宇",@"金志文",@"趙英俊"];
return _songAuthorArr;
}
#pragma mark---歌曲圖片的數組
-(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時傳入歌曲的網址數組跟歌曲的背景圖片數組便可實現當前歌曲播放結束后,自動播放下一首并切換player的背景圖片(支持本地圖片和網絡圖片)
- (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];
//設置volume,不設置默認為0.5
_player.volume=0.8;
[self.view addSubview:_player];
}
實現代理方法可自動返回當前時間,總共時間,歌曲進度以及點擊次數,并且時間的格式已經轉換成00:00的格式
#pragma mark----SZKAVPlayerDelegate代理方法
-(void)getSongCurrentTime:(NSString *)currentTime andTotalTime:(NSString *)totalTime andProgress:(CGFloat)progress andTapCount:(NSInteger)tapCount
{
//進度條
[_progressView setProgress:progress];
//歌曲時間
_songTime.text=[NSString stringWithFormat:@"%@/%@",currentTime,totalTime];
//歌曲名稱
_songName.text=self.songNameArr[tapCount];
//歌曲演唱者
_songAuthor.text=self.songAuthorArr[tapCount];
}
player的其他操作調用SZKAVPlayer.h中相關的API即可
/**
* 開始播放
*/
-(void)startPlay;
/**
* 暫停播放
*/
-(void)puasePlay;
/**
* 播放下一首
*/
-(void)nextSong;
/**
* 播放上一首
*/
-(void)lastSong;
最終效果圖:
SZKAVPlayer的調用方法大致就是這樣,只需要在初始化時傳入歌曲數組和歌曲圖片,便可實現當前歌曲結束后,自動播放下一首,同時切換歌曲圖片,并且代理方法中的歌曲的當前時間,總共時間以及播放進度,也會隨著歌曲的切換而自動刷新。
下面大致介紹一下SZKAVPlayer.m的實現方法
songItem和player用來初始化SZKAVPlayer
//初始化songItem和player
_songItem=[AVPlayerItem playerItemWithURL:url];
_player=[AVPlayer playerWithPlayerItem:_songItem];
[_player play];
并對播放器添加了三個監聽和一個通知
#pragma mark----監聽播放器的加載狀態
-(void)addAVPlayerStatusObserver
{
[_songItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
}
#pragma mark----數據緩沖狀態的監聽
-(void)addNetDataStatusObserver
{
[_songItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];
}
#pragma mark----添加觀察者監聽獲取當前時間,總共時間,進度
-(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) {
//設置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]];
}
}
//當前時間
float current=CMTimeGetSeconds(time);
//總共時間
float total=CMTimeGetSeconds(songItem.duration);
//進度
float progress=current/total;
//將值傳入知道delegate方法中
[bself.delegate getSongCurrentTime:[bself formatTime:current] andTotalTime:[bself formatTime:total] andProgress:progress andTapCount:bself.tapCount];
}];
}
#pragma mark----播放完成后發送通知
-(void)addPlayToEndObserver
{
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(playFinished:) name:AVPlayerItemDidPlayToEndTimeNotification object:_songItem];
}
為了防止在進行下一首歌曲時候監聽出錯,在當前歌曲結束后移除所有監聽,在下一首歌曲播放前再次添加監聽,筆者親測目前這樣寫沒有出現什么問題。
大致的功能原理先寫到這,筆者第一次寫,不足的地方還望各位讀者見諒,如果遇到什么問題,可以評論回復,筆者收到后第一時間回復大家,也可以添加筆者的QQ/微信:790057066 ,并且剛剛把demo上傳到了GitHub上面感興趣的朋友,可以上去下載查看,記得star下,非常感謝。
SZKAVPlayer鏈接 https://github.com/18811314750/SZKAVPlayer
筆者的其他文章
iOS開發-利用命令行實現將本地代碼上傳到GitHub
http://www.lxweimin.com/p/79b94add9057
iOS開發-快速調用照相機和相冊,并實現沙盒中照片的保存與讀取
http://www.lxweimin.com/p/7ffc8844e956