一、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设置委托是必须的:

  1. player.delegate = self;
  1. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer*)player successfully:(BOOL)flag{
  2. //播放结束时执行的动作
  3. }
  4. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer*)player error:(NSError *)error{
  5. //解码错误执行的动作
  6. }
  7. - (void)audioPlayerBeginInteruption:(AVAudioPlayer*)player{
  8. //处理中断的代码
  9. }
  10. - (void)audioPlayerEndInteruption:(AVAudioPlayer*)player{
  11. //处理中断结束的代码
  12. }

 三、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的更多相关文章

  1. iOS播放器 - AVAudioPlayer

    今天记录一下AVAudioPlayer,这个播放器类苹果提供了一些代理方法,主要用来播放本地音频. 其实也可以用来播放网络音频,只不过是将整个网络文件下载下来而已,在实际开发中会比较耗费流量不做推荐. ...

  2. AVAudioPlayer播放本地音频

    AVAudioPlayer苹果官方上说一般用于播放本地音频,不能用于播放网络上的音频. 具体的代码:先导入 #import <AVFoundation/AVFoundation.h> // ...

  3. AVAudioPlayer播放并实现了后台播放和远程控制

    // ViewController.h #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @class ...

  4. iOS -- AVAudioPlayer播放音乐

    一. AVAudioPlayer:                          声明音乐控件AVAudioPlayer,必须声明为全局属性变量,否则可能不会播放,AVAudioPlayer只能播 ...

  5. initializer for conditional binding must have optional type not AVAudioPlayer

    if let buttonBeep = self.setupAudioPlayerWithFile("ButtonTap", type: "wav") {    ...

  6. iOS - AVAudioPlayer 音频播放

    前言 NS_CLASS_AVAILABLE(10_7, 2_2) @interface AVAudioPlayer : NSObject @available(iOS 2.2, *) public c ...

  7. 音乐播放器 AVAudioPlayer、定时器、UISlider

    #import <UIKit/UIKit.h> #import <AVFoundation/AVFoundation.h> @interface ViewController ...

  8. AVAudioplayer时error解决 创建失败 ERror creating player: Error Domain=NSOSStatusErrorDomain Code=2003334207 "(null)"

    AVAudioplayer 有两个初始化方法: 1.[[AVAudioPlayer alloc] initWithData:musicData error&e]; 2.[[AVAudioPla ...

  9. IOS AVAUDIOPLAYER 播放器使用

    1. 导入 AVFoundation.framework 2.导入头文件  #import <AVFoundation/AVFoundation.h> 3. player = [[AVAu ...

随机推荐

  1. 第10章 Shell编程(1)_正则表达式

    1. 基础的正则表达式 1.1 正则表达式与通配符 (1)正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配.grep.awk.sed等命令可以支持正则表达式. (2)通配符用来匹配符合条件的 ...

  2. 解读ASP.NET 5 & MVC6系列(10):Controller与Action

    我们知道在MVC5和之前的版本,两个框架的生命周期是不一样的,在新版MVC6中,MVC Controller/Web API Controller已经合二为一了,本章我们主要讲解Controller和 ...

  3. chrome中获取元素的样式

    以获取背景颜色为例 html部分 <div id="test">abcd</div> css部分 #test { background-color: rgb ...

  4. oracle日常——sqlplus客户端登录

    1.进入cmd 2.命令--sqlplus--提示输入帐号与密码 3.进入后,就可以直接键入sql命令 ps.sql命令后面需要添加分号后才可以回车执行

  5. Python 日常积累

    包管理 >from ... import ... 的用法和直接import的区别 直接使用import时,如果需要使用到导入模块内的属性和方法,必须使用模块名.属性和模块名.方法的方式进行调用 ...

  6. 学习Struts2的第一个应用步骤

    ---恢复内容开始--- 一.在官网 http://struts.apache.org/下载struts-2.3.31-all 1.  打开struts-2.3.31-all,将struts-2.3. ...

  7. com/android/dx/command/dexer/Main : Unsupported major.minor version 52.0

    这是由于JDK版本不一致造成的,指的是高版本的JDK编译的class不能放在低版本的JDK上运行. Version 52,表示JDK8编译的class不能运行在JDK7上,所以需要在本地安装JDK8.

  8. 纯css,编写菜单移入效果

    <!doctype html><html lang="en"><head> <meta charset="UTF-8" ...

  9. cookie

    1.基本操作 Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给 ...

  10. sublime text3 使用SVN插件

    Simon在项目中经常使用SVN,每次都要切换提交,很麻烦,有了这个SVN插件就很方便了,使用快捷方式提交,更新. 安装: Ctrl + Shift + P 调用出Sublime Text的包管理工具 ...