由于本人學(xué)識(shí)尚淺如有不對(duì)請(qǐng)大神加以指正。
本文主要講解AVPlayer的基本使用和簡單封裝尘颓,主要使用AVPlayer做音樂播放公给。
AVPlayer在使用之前應(yīng)了解:
AVPlayer 的rate屬性 這個(gè)屬性表示AVPlayer的播放狀態(tài) 0暫停 1播放
AVPlayerItem 媒體資源管理對(duì)象,每個(gè)AVPlayerItem對(duì)應(yīng)一個(gè)視頻或音頻資源
AVPlayerItemStatus 視頻音頻播放狀態(tài)
typedef NS_ENUM(NSInteger, AVPlayerItemStatus) {
AVPlayerItemStatusUnknown,未知資源
AVPlayerItemStatusReadyToPlay,準(zhǔn)備播放
AVPlayerItemStatusFailed 加載失敗
};
AVPlayerItem 的播放完成通知
AVPlayerItemDidPlayToEndTimeNotification
AVPlayer 監(jiān)控播放時(shí)間的方法 用于更新進(jìn)度條
- (id)addPeriodicTimeObserverForInterval:(CMTime)interval queue:(nullable dispatch_queue_t)queue usingBlock:(void (^)(CMTime time))block;
AVPlayer 設(shè)置播放時(shí)間
- (void)seekToTime:(CMTime)time completionHandler:(void (^)(BOOL finished))completionHandler NS_AVAILABLE(10_7, 5_0);
播放音樂
//播放網(wǎng)絡(luò)音樂
AVPlayerItem *playerItem姚糊;
NSURL *url=[NSURL URLWithString:"音樂鏈接字符串"];
playerItem=[[AVPlayerItem alloc]initWithURL:url];
//播放項(xiàng)目中的音樂
NSString *audioPath = [[NSBundle mainBundle] pathForResource:@"音樂名" ofType:@"格式"];
NSURl *audioUrl = [NSURL fileURLWithPath:audioPath];
playerItem=[[AVPlayerItem alloc]initWithURL:audioUrl];
//播放下載在document中的音樂
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *fullPath=[documentsDirectory stringByAppendingPathComponent:fileName];
NSURL *musicUrl=[NSURL fileURLWithPath:fullPath];
playerItem=[[AVPlayerItem alloc]initWithURL:url];
以上就是音樂的播放了
現(xiàn)在講解對(duì)AVPlayer的簡單封裝
MusicManger.h
首先引入AVFoundation框架
#import<AVFoundation/AVFoundation.h>
自己的音樂實(shí)體類
#import "Music.h"
設(shè)置代理協(xié)議
@protocol MusicMangerDelegate <NSObject>
@optional
-(void)updateProgressByCurrentTime:(float)currentPlayTime totalTime:(float)totalTime timeStr:(NSString *)str;
-(void)updateBufferProgress:(NSTimeInterval)progress;
-(void)updateCurrentMusic:(Music *)aMusic;
@end
設(shè)置功能函數(shù)
@interface MusicManager : NSObject
@property (weak,nonatomic) id<MusicMangerDelegate>delegate;
+(instancetype)defaultManager;
-(void)playMusic:(Music *)aMusic musicArray:(NSArray *)array index:(NSInteger)index;
-(void)playerProgressChanged:(float)currentProgress;
-(BOOL)play;
-(void)pause;
-(void)playNext;
-(void)playPrevious;
@end
MusicManger.m
#import "MusicManager.h"
@interface MusicManager ()
@property (strong,nonatomic) AVPlayer *player;
@property (strong,nonatomic) NSTimer *timer;
@property (strong,nonatomic) Music *aMusic;
@property (strong,nonatomic) NSArray *musicArray;
@property (assign,nonatomic) NSInteger index;
@end
@implementation MusicManager
//AVPlayer懶加載
-(AVPlayer *)player
{
if(_player==nil)
{
_player=[[AVPlayer alloc]init];
[_player addObserver:self forKeyPath:@"rate" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
}
return _player;
}
//程序的入口
-(void)playMusic:(Music *)aMusic musicArray:(NSArray *)array index:(NSInteger)index
{
if (aMusic&&array!=nil&&index>=0) {
self.musicArray=array;
self.index=index;
[self addObserver:self forKeyPath:@"aMusic" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[self playCurrentMusic:aMusic];
}else
{
NSLog(@"未傳入aMusic或musicList或index");
return;
}
}
//播放當(dāng)前音樂
-(void)playCurrentMusic:(Music *)aMusic
{
static Music *theMusic;
if (theMusic==aMusic) {
return;
}else{
AVPlayerItem *playerItem遏弱;
NSString *urlStr=[NSString stringWithFormat:@"%@",aMusic.musicLink];
NSString *encodingStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:encodingStr];
playerItem=[[AVPlayerItem alloc]initWithURL:url];
//播放前移除playerItem的系列觀察者
[self currentItemRemoveObserver];
[self.player replaceCurrentItemWithPlayerItem:playerItem];
//為playerItem添加觀察者
[self currentItemAddObserver];
theMusic=aMusic;
}
-(void)currentItemAddObserver
{
//監(jiān)控AVPlayer的status屬性獲得播放狀態(tài)
[self.player.currentItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//監(jiān)控緩沖加載情況屬性獲取緩沖情況
[self.player.currentItem addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//AVPlayerTimeControlStatus
//監(jiān)控播放完成通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
//監(jiān)控當(dāng)前播放時(shí)間
__weak typeof (self) WeakSelf=self;
_timer=[_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 5) queue:dispatch_get_main_queue() usingBlock:^(CMTime time)
{
float currentTime = WeakSelf.player.currentItem.currentTime.value/WeakSelf.player.currentItem.currentTime.timescale;
float duration=CMTimeGetSeconds(WeakSelf.player.currentItem.duration);
NSString *timeStr=[WeakSelf timeStringFromSecond:currentTime];
if (self.delegate&&[self.delegate respondsToSelector:@selector(updateProgressByCurrentTime:totalTime:timeStr:)])
{
//將獲得的音樂信息通過代理傳出去
[WeakSelf.delegate updateProgressByCurrentTime:currentTime totalTime:duration timeStr:timeStr];
}
}];
}
//播放完成自動(dòng)播放下一曲
-(void)playNext
{
if (self.index==self.musicArray.count-1) {
self.index=0;
}else
{
self.index++;
}
self.aMusic=self.musicArray[self.index];
[self playCurrentMusic:self.aMusic];
}
//移除playItem的觀察者
-(void)currentItemRemoveObserver
{
[self.player.currentItem removeObserver:self forKeyPath:@"status"];
[self.player.currentItem removeObserver:self forKeyPath:@"loadedTimeRanges"];
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
[self.player removeTimeObserver:_timer];
}
//播放音樂
-(BOOL)play
{
if (self.player.status==AVPlayerStatusReadyToPlay) {
[self.player play];
return YES;
}
return NO;
}
//暫停播放
-(void)pause
{
[self.player pause];
}
//播放下一曲
-(void)playNext
{
if (self.index==self.musicArray.count-1) {
self.index=0;
}else
{
self.index++;
}
self.aMusic=self.musicArray[self.index];
[self playCurrentMusic:self.aMusic];
}
//播放上一曲
-(void)playPrevious
{
if (self.index==0) {
self.index=self.musicArray.count-1;
}else
{
self.index--;
}
self.aMusic=self.musicArray[self.index];
[self playCurrentMusic:self.aMusic];
}
這里KVO的實(shí)現(xiàn)和代理的實(shí)現(xiàn)
//KVO觀察屬性變化
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context
{
AVPlayerItem *playerItem=object;
//播放狀態(tài)
if ([keyPath isEqualToString:@"status"]) {
AVPlayerItemStatus status=[change[@"new"]integerValue];
switch (status) {
//資源加載成功
case AVPlayerItemStatusReadyToPlay:
{
[self.player play];
}
break;
case AVPlayerItemStatusFailed:
{
NSLog(@"加載失敗,播放出錯(cuò)");
}
break;
case AVPlayerItemStatusUnknown:
{
NSLog(@"未知資源播放錯(cuò)誤");
}
break;
default:
break;
}
}
//緩沖時(shí)間
else if([keyPath isEqualToString:@"loadedTimeRanges"])
{
NSArray *bufferArray=playerItem.loadedTimeRanges
;
CMTimeRange timeRange=[bufferArray.firstObject CMTimeRangeValue];
float startSeconds=CMTimeGetSeconds(timeRange.start);
float durationSeconds=CMTimeGetSeconds(timeRange.duration);
NSTimeInterval totalBuffer=startSeconds+durationSeconds;
NSLog(@"共緩沖:%.2f",totalBuffer);
if(self.delegate&&[self.delegate respondsToSelector:@selector(updateBufferProgress:)])
{
//將緩沖時(shí)間通過代理傳出去
[self.delegate updateBufferProgress:totalBuffer];
}
}
//音樂對(duì)象的變化
else if ([keyPath isEqualToString:@"aMusic"])
{
Music *currentMusic=change[@"new"];
[[NSNotificationCenter defaultCenter]postNotificationName:@"currentMusic" object:currentMusic];
if (self.delegate&&[self.delegate respondsToSelector:@selector(updateCurrentMusic:)]) {
[self.delegate updateCurrentMusic:currentMusic];
}
}
//當(dāng)前音樂的播放狀態(tài)
else if ([keyPath isEqualToString:@"rate"])
{
NSString *rate=change[@"new"];
NSLog(@"%@",rate);
//利用通知中心將當(dāng)前播放狀態(tài)傳出去
[[NSNotificationCenter defaultCenter]postNotificationName:@"isPlaying" object:rate];
}
}
最后感謝大家能看到最后
demo的話以后會(huì)上傳