AVAudioPlayer
一、AVAudioPlayer简介
AVAudioPlayer在AVFoundation框架下,所以我们要导入AVFoundation.framework。
AVAudioPlayer类封装了播放单个声音的能力。播放器可以用NSURL或者NSData来初始化,要注意的是NSURL并不可以是网络url而必须是本地文件URL,
因为 AVAudioPlayer不具备播放网络音频的能力,如果要播放网络URL,需要先转化为NSData.但是此法并不可取,
因为AVAudioPlayer只能播放一个完整的文件,并不支持流式播放,所以必须是缓冲完才能播放,所以如果网络文件过大抑或是网速不够岂不是要等很久?
所以播放网络音频我们一般用音频队列。播放较大的音频或者要对音频有精确的,这种情况会选择使用AVFoundation.framework中的AVAudioPlayer来实现。
AVAudioPlayer不支持边下边播,所以只能下载到本地再播放,这是他的缺点。但是AVAudioPlayer能够精确控制播放进度、音量、播放速度等属性,这是很强大的优点。
注意:需要添加AVFoundation.framework
二、AVAudioPlayer使用
1.实例化方法
- (instancetype)initWithContentsOfURL:(NSURL *)url error:(NSError **)outError;
2.预加载资源
- (BOOL)prepareToPlay;
3.遵守协议
AVAudioPlayerDelegate
4.播放完成之后回调以下方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
先搭建UI吧,直接上图:
#import "AVAudioPlayerViewController.h"
#import <AVFoundation/AVFoundation.h> @interface AVAudioPlayerViewController ()
{
//声明一个播放器
AVAudioPlayer *_musicPlay;//音乐播放器
} - (IBAction)playAction:(id)sender;//播放
- (IBAction)pauseAction:(id)sender;//暂停
- (IBAction)voiceAction:(UISlider *)sender;//音量
- (IBAction)progressAction:(UISlider *)sender;//进度 @property (weak, nonatomic) IBOutlet UISlider *progressSlider;//进度条
@property (nonatomic,strong)NSTimer *myTimer;//声明一个定时器类型的成员变量 @end @implementation AVAudioPlayerViewController - (void)viewDidLoad {
[super viewDidLoad]; //获取资源路径 需要事先导入本地音频内容
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"1" ofType:@"mp3"];
NSLog(@"%@",filePath); NSURL *URL =[NSURL fileURLWithPath:filePath];
_musicPlay = [[AVAudioPlayer alloc] initWithContentsOfURL:URL error:nil];
//实例化音乐播放器
// _musicPlay = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:filePath] error:nil]; //设置音量大小处于中等强度
_musicPlay.volume = 0.5;
//循环次数,默认是1
_musicPlay.numberOfLoops = 1;
// 声道数
NSUInteger channels = _musicPlay.numberOfChannels;//只读属性 //预加载资源
if ([_musicPlay prepareToPlay]) { NSLog(@"准备完毕"); } //设置总进度大小
self.progressSlider.maximumValue = _musicPlay.duration; }
#pragma mark- 各类触发事件
-(void)change:(NSTimer *)sender{ //每一秒钟设置一下进度值 播放位置
self.progressSlider.value = _musicPlay.currentTime; } #pragma mark- AVAudioPlayer相关的方法
- (IBAction)playAction:(id)sender {
//播放
[_musicPlay play]; self.myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(change:) userInfo:nil repeats:YES];
} - (IBAction)pauseAction:(id)sender {
//暂停
[_musicPlay pause];
//停止定时器
[self.myTimer invalidate];
NSLog(@"%f",_musicPlay.currentTime);
} - (IBAction)voiceAction:(UISlider *)sender { //改变音量大小
_musicPlay.volume = sender.value; } - (IBAction)progressAction:(UISlider *)sender { //设置进度
_musicPlay.currentTime = sender.value; }
代理方法
加入播放出现异常,或者被更高级别的系统任务打断,我们的程序还没来得及收场就挂了,怎么办?不急,我们可以通过几个委托方法很好地处理所有的情形。
首先给player设置委托是必须的:
- player.delegate = self;
- - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player successfully:(BOOL)flag{
- //播放结束时执行的动作
- }
- - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer*)player error:(NSError *)error{
- //解码错误执行的动作
- }
- - (void)audioPlayerBeginInteruption:(AVAudioPlayer*)player{
- //处理中断的代码
- }
- - (void)audioPlayerEndInteruption:(AVAudioPlayer*)player{
- //处理中断结束的代码
- }
三、AVAudioPlayer扩展
1) 如何做后台播放
1> 在plist文件下添加 key : Required background modes,并设置item0 = App plays audio or streams audio/video using AirPlay
2> 设置AVAudioSession的类型为AVAudioSessionCategoryPlayback并且调用setActive::方法启动会话。
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
[audioSession setActive:YES error:nil];
正常来说,当app退到后台,程序处于悬挂状态,即暂停播放。
在iOS中每个应用都有一个音频会话,这个会话就通过AVAudioSession来表示。
AVAudioSession同样存在于AVFoundation框架中,它是单例模式设计,通过sharedInstance进行访问。在使用Apple设备时大家会发现有些应用只要打开其他音频播放就会终止,而有些应用却可以和其他应用同时播放,在多种音频环境中如何去控制播放的方式就是通过音频会话来完成的。
下面是音频会话的几种会话模式:
注意 : 前面的代码中也提到设置完音频会话类型之后需要调用setActive::方法将会话激活才能起作用。
(2) 如何做输出改变监听(拔出耳机音乐暂停播放)
ios6.0后还可以监听输出改变通知。通俗来说,就是拔出耳机,音乐播放暂停。
代码如下:
//添加观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];
// 通知方法
- (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"])
{
//这边必须回调到主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.playOrPause.selected = NO;
});
[self pauseMusic];
}
}
}//输出改变通知
(3) 歌词轮播实现思路
歌词应该是 时间 和 对应歌词 的字典类型数据结构。用UITableView实现。获取播放器当前播放时间,查找字典找到对应的key,进而找到对应的NSIndexPath,滚动到当前cell在屏幕中央即可。
(4) 关于定时器的小细节
关于NSLoopMode的问题
由于+ (NSTimer *)scheduledTimerWithTimeInterval:..; 此时的timer会被加入到当前线程的runloop中,默认为NSDefaultRunLoopMode。如果当前线程是主线程,某些事件,如UIScrollView的拖动时,会将runloop切换到NSEventTrackingRunLoopMode模式,在拖动的过程中,默认的NSDefaultRunLoopMode模式中注册的事件是不会被执行的。从而此时的timer也就不会触发。
解决方案:把创建好的timer手动添加到指定模式中,此处为NSRunLoopCommonModes,这个模式其实就是NSDefaultRunLoopMode与NSEventTrackingRunLoopMode的结合。
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
AVAudioPlayer的更多相关文章
- iOS播放器 - AVAudioPlayer
今天记录一下AVAudioPlayer,这个播放器类苹果提供了一些代理方法,主要用来播放本地音频. 其实也可以用来播放网络音频,只不过是将整个网络文件下载下来而已,在实际开发中会比较耗费流量不做推荐. ...
- AVAudioPlayer播放本地音频
AVAudioPlayer苹果官方上说一般用于播放本地音频,不能用于播放网络上的音频. 具体的代码:先导入 #import <AVFoundation/AVFoundation.h> // ...
- AVAudioPlayer播放并实现了后台播放和远程控制
// ViewController.h #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @class ...
- iOS -- AVAudioPlayer播放音乐
一. AVAudioPlayer: 声明音乐控件AVAudioPlayer,必须声明为全局属性变量,否则可能不会播放,AVAudioPlayer只能播 ...
- initializer for conditional binding must have optional type not AVAudioPlayer
if let buttonBeep = self.setupAudioPlayerWithFile("ButtonTap", type: "wav") { ...
- iOS - AVAudioPlayer 音频播放
前言 NS_CLASS_AVAILABLE(10_7, 2_2) @interface AVAudioPlayer : NSObject @available(iOS 2.2, *) public c ...
- 音乐播放器 AVAudioPlayer、定时器、UISlider
#import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface ViewController ...
- AVAudioplayer时error解决 创建失败 ERror creating player: Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)"
AVAudioplayer 有两个初始化方法: 1.[[AVAudioPlayer alloc] initWithData:musicData error&e]; 2.[[AVAudioPla ...
- IOS AVAUDIOPLAYER 播放器使用
1. 导入 AVFoundation.framework 2.导入头文件 #import <AVFoundation/AVFoundation.h> 3. player = [[AVAu ...
随机推荐
- JBPM工作流
一.开发环境的搭建 1.下载Jbpm4.4 1.1下载地址: https://sourceforge.net/projects/jbpm/files/jBPM%204/jbpm-4.4/ 1.2解压后 ...
- Maven打包含有Main方法jar并运行
最近使用Kettle做定时数据抽取,因为Job更新或需求变更,修改Bug等种种原因,需要对重跑Job一般是针对每天的数据重跑一次.刚开始的做法是直接在自己的开发机器上重跑,这样速度比较慢,因为这时候你 ...
- 解读ASP.NET 5 & MVC6系列(11):Routing路由
新版Routing功能介绍 在ASP.NET 5和MVC6中,Routing功能被全部重写了,虽然用法有些类似,但和之前的Routing原理完全不太一样了,该Routing框架不仅可以支持MVC和We ...
- redis配置文件详解
基于redis2.4版本的配置文件. # 注意单位问题:当需要设置内存大小的时候,可以使用类似1k.5GB.4M这样的常见格式:## 1k => 1000 bytes# 1kb => 10 ...
- adb devices 偵測不到 手機
現象: system 有偵測到 mobile phone, xxx@xxx-ThinkPad-T460p:~/.android$ lsusb Bus Device : ID 1d6b: Linux F ...
- webpack构建vue项目(再谈配置)
webpack配置起来确实麻烦,这不,之前用刚配好了vue1+的版本,结果在(部分)安卓机上测试,发现存在开启热加载(dev-server)的情况下不能识别vue语法的问题,试了很多方法,都没能很好的 ...
- [转]ExtJs基础--Html DOM、Ext Element及Component三者之间的区别
要学习及应用好Ext框架,必须需要理解Html DOM.Ext Element及Component三者之间的区别. 每一个HTML页面都有一个层次分明的DOM树模型,浏览器中的所有内容都有相应的DOM ...
- iOS中富文本NSMutableAttributedString的用法
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc]initWithString:@"我是富文 ...
- Rabin-Karp指纹字符串查找算法
首先计算模式字符串的散列函数, 如果找到一个和模式字符串散列值相同的子字符串, 那么继续验证两者是否匹配. 这个过程等价于将模式保存在一个散列表中, 然后在文本中的所有子字符串查找. 但不需要为散列表 ...
- Mysql数据库 - 增删改
一. Create 1. 单条插入, sql格式: insert into (列名) values(列值); INSERT INTO test.tch_teacher ( Sex, BId, NO, ...