简述
AVAudioPlayer 是一个属于 AVFoundation.framework
的一个类,它的功能类似于一个功能强大的播放器,AVAudioPlayer 支持广泛的音频格式,主要是以下这些格式。
- AAC
- AMR (Adaptive multi-Rate,一种语音格式)
- ALAC (Apple lossless Audio Codec)
- iLBC (internet Low Bitrate Codec,另一种语音格式)
- IMA4 (IMA/ADPCM)
- linearPCM (uncompressed)
- u-law 和 a-law
- MP3 (MPEG-Laudio Layer 3)
AVAudioPlayer 的使用
AVAudioPlayer 初始化
initWithContentsOfURL: error:
从URL加载音频,返回 AVAudioPlayer 对象initWithData: error:
加载NSdata对象的音频文件,返回 AVAudioPlayer 对象
AVAudioPlayer方法调用
- (BOOL)play
开始或恢复播放,调用该方法时,如果该音频还没有准备好,程序会隐士执行- (BOOL)prepareToPlay
方法- (void)pause
暂停- (void)stop
停止- (BOOL)playAtTime:(NSTimeInterval)time NS_AVAILABLE(10_7, 4_0)
在某个时间点播放- (BOOL)prepareToPlay
准备开始播放- (void)updateMeters
更新音频测量值,注意如果要更新音频测量值必须设置meteringEnabled为YES,通过音频测量值可以即时获得音频分贝等信息- (float)averagePowerForChannel:(NSUInteger)channelNumber
获得指定声道的分贝峰值,注意如果要获得分贝峰值必须在此之前调用updateMeters方法
使用 AVAudioPlayer 读取音频信息
volume
播放器的音频增益,值:0.0~1.0pan NS_AVAILABLE(10_7, 4_0)
立体声设置 设为-1.0
则左边播放 设为0.0
则中央播放 设为1.0
则右边播放enableRate
是否允许改变播放速率rate NS_AVAILABLE(10_8, 5_0)
播放速率0.5
(半速播放) ~2.0
(倍速播放) 注1.0
是正常速度playing
是否正在播放音频numberOfLoops
循环次数,如果要单曲循环,设置为负数numberOfChannels
该音频的声道次数 (只读)duration
该音频时长currentTime
该音频的播放点deviceCurrentTime
输出设备播放音频的时间,注意如果播放中被暂停此时间也会继续累加url
音频文件路径,只读data
音频数据,只读channelAssignments
获得或设置播放声道
代理方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
音频播放完成- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error
音频解码发生错误- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
如果音频被中断,比如有电话呼入,该方法就会被回调,该方法可以保存当前播放信息,以便恢复继续播放的进度
代码
AVAudioPlayer 初始化
首先导入两首格式为 mp3 的歌曲,再导入歌手图片
在 ViewController.h 导入
#import#import 复制代码
然后必须持有一个 AVAudioPlayer 对象,若此对象不是属性,则无法播放
@property (nonatomic , strong) AVAudioPlayer *player;复制代码
添加控件如图所示,给控件命名
获取制定 url 对象
NSURL *url = [[NSBundle mainBundle] URLForResource:@"吴亦凡-时间煮雨" withExtension:@"mp3"];复制代码
初始化 AVAudioPlayer 对象
self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];复制代码
设置代理
self.player.delegate = self;复制代码
这样就播放器就初始化完成了
将storyboard里面 开始
按钮绑定 - (IBAction)start:(id)sender
方法
- (IBAction)start:(id)sender { if ([self.player isPlaying]) { [self.startBtn setBackgroundImage:[UIImage imageNamed:@"播放"] forState:0]; [self.player pause]; } else { [self.startBtn setBackgroundImage:[UIImage imageNamed:@"暂停"] forState:0]; [self.player play]; } if (_timer == nil) { _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES]; } }复制代码
注: 上诉代码中定义了一个 NSTimer
变量,因为播放器没有播放进程的委托,所以只能自定义NSTimer变量对播放器进行监控
@property (strong, nonatomic) NSTimer *timer;复制代码
将storyboard里面 停止
按钮绑定 - (IBAction)stop:(id)sender
方法
- (IBAction)stop:(id)sender { [self.player stop]; //计时器停止 [_timer invalidate]; //释放定时器 _timer = nil;}复制代码
设置刚才绑定的定时器调用方法updateProgress
-(void)updateProgress{ //进度条显示播放进度 self.progress.progress = self.player.currentTime/self.player.duration; self.info1.text = [NSString stringWithFormat:@"当前播放时间%f",self.player.currentTime];}复制代码
实现 AVAudioPlayer
的委托方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{ if (player == _player && flag) { [self.startBtn setBackgroundImage:[UIImage imageNamed:@"播放"] forState:0]; }}-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{ if (player == _player){ NSLog(@"播放被中断"); }}复制代码
此时,音乐就可以播放了!!!
但是,人们使用音乐大都是后台播放,那么如何添加后台播放支持呢?
后台播放
在项目里 info.plist
右键 open As
-- source code
添加代码:
UIBackgroundModes 复制代码 audio
同样,代码里面也要添加后台播放支持
//设置锁屏仍能继续播放[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:nil];[[AVAudioSession sharedInstance] setActive: YES error: nil];复制代码
这样 音乐在后台就可以播放了!!
那么很多播放器都有一个功能,那就是在用户拔掉耳机的时候,暂停播放
监听播放设备
//添加通知,拔出耳机后暂停播放[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil]; /** * 一旦输出改变则执行此方法 * * @param notification 输出改变通知对象 */-(void)routeChange:(NSNotification *)notification{ NSDictionary *dic=notification.userInfo; int changeReason= [dic[AVAudioSessionRouteChangeReasonKey] intValue]; //等于AVAudioSessionRouteChangeReasonOldDeviceUnavailable表示旧输出不可用 if (changeReason==AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { AVAudioSessionRouteDescription *routeDescription=dic[AVAudioSessionRouteChangePreviousRouteKey]; AVAudioSessionPortDescription *portDescription= [routeDescription.outputs firstObject]; //原设备为耳机则暂停 if ([portDescription.portType isEqualToString:@"Headphones"]) { [self.player pause]; } }}复制代码
这样就能在拔掉耳机的时候,暂停播放了!!!
但是似乎还是差了一些什么,好像锁屏界面空空如也啊!!!
定制锁屏界面
设置后台播放时显示的东西,例如歌曲名字,图片等
要用到 <MediaPlayer/MediaPlayer.h>
这个库,刚才已经导入过
- (void)setPlayingInfo { // 设置后台播放时显示的东西,例如歌曲名字,图片等 MPMediaItemArtwork *artWork = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"吴亦凡.jpg"]]; NSDictionary *dic = @{MPMediaItemPropertyTitle:@"时间煮雨", MPMediaItemPropertyArtist:@"吴亦凡", MPMediaItemPropertyArtwork:artWork }; [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dic];}复制代码
这样,图片就在锁屏界面显示了,不过,锁屏界面上面的三个按钮,怎么控制播放呢!!
接收锁屏歌曲按钮控制 (上一首,播放,下一首)
首先,你要在一个继承 UIResponder
类里面接收远程控制,本文以 ViewController 为例
添加如下代码,接受远程控制和取消远程控制。
- (void)viewDidAppear:(BOOL)animated { // 接受远程控制 [self becomeFirstResponder]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];}- (void)viewDidDisappear:(BOOL)animated { // 取消远程控制 [self resignFirstResponder]; [[UIApplication sharedApplication] endReceivingRemoteControlEvents];}复制代码
接收方法设置
- (void)remoteControlReceivedWithEvent:(UIEvent *)event { if (event.type == UIEventTypeRemoteControl) { //判断是否为远程控制 switch (event.subtype) { case UIEventSubtypeRemoteControlPlay: if (![_player isPlaying]) { [_player play]; } break; case UIEventSubtypeRemoteControlPause: if ([_player isPlaying]) { [_player pause]; } break; case UIEventSubtypeRemoteControlNextTrack: NSLog(@"下一首"); break; case UIEventSubtypeRemoteControlPreviousTrack: NSLog(@"上一首 "); break; default: break; } }}复制代码
效果图:
这样,播放器的基本功能就已经完成 !! 代码多有不祥之处,时间匆忙,敬请谅解,不实之处,请多包涵!!
Demo地址: