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 ...
随机推荐
- [游戏开发-学习笔记]菜鸟慢慢飞(九)- NGUI- UIPanel(官方说明翻译)
我自己笔记是做在OneNote上,直接复制粘贴过来变成图片了,效果好像还可以. 机器翻译,我自己看了一下,改了一部分.
- [LeetCode] Binary Tree Preorder Traversal 二叉树的先序遍历
Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...
- [LeetCode] Add Binary 二进制数相加
Given two binary strings, return their sum (also a binary string). For example,a = "11"b = ...
- [EF1]POCOs(Plain Old C# Object)Entity Framework 4.x: POCOs入门
原文链接:http://www.cnblogs.com/hjzhang/archive/2011/05/18/2050530.html POCOs 是在Visual Studio 2010和ASP.N ...
- ajax处理缓冲问题
1.禁止页面缓存 header("Cache-Control:no-cache"); header("Pragma:no-cache"); header(&qu ...
- vector迭代器用法
#include<iostream> #include<vector> using namespace std; int main() { vector<int> ...
- iOS常用开发技巧
iOS开发过程中,总有那么一些个小问题让人纠结,它们不会让程序崩溃,但是会让人崩溃.除此之外,还将分享一些细节现在我通过自己的总结以及从其他地方的引用,来总结一下一些常见小问题. 本篇长期更新,多积累 ...
- css-css权威指南学习笔记8
第十二章 列表与生成内容 1.list-style-type:cjk-ideographic生成一二三四的序号 2.不管是ul还是ol,list-style-type无法识别的值都应用为decimal ...
- bitset用法总结
b.any() b中是否存在置为1的二进制位? b.none() b中不存在置为1的二进制位吗? b.count() b中置为1的二进制位的个数 b.size() b中二进制位的个数 b[pos] 访 ...
- JavaScript replace() 方法
参考:http://www.w3school.com.cn/jsref/jsref_replace.asp 需要有一点注意的是:可以是函数的形式做为返回值,如下: "test{0}" ...