iOS音频播放的几种方式

一、使用AVAudioPlayer播放音乐

1. Background Modes

打开后台模式的音乐播放,或者在info.plist文件中添加Required Background Modes键,其值是App plays audio or streams audio/video using AirPlay

Background Modes

2. 添加后台播放代码

1
2
3
4
5
AVAudioSession *session = [AVAudioSession sharedInstance];

[session setActive:YES error:nil];

[session setCategory:AVAudioSessionCategoryPlayback error:nil];

3. 播放指定的音频文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 1.获取要播放音频文件的URL
NSURL *fileURL = [[NSBundle mainBundle]URLForResource:@"王力宏-流泪手心" withExtension:@".mp3"];

// 2.创建 AVAudioPlayer 对象
self.audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:fileURL error:nil];

// 3.打印歌曲信息
NSString *msg = [NSString stringWithFormat:@"音频文件声道数:%ld\n 音频文件持续时间:%g",self.audioPlayer.numberOfChannels,self.audioPlayer.duration];
NSLog(@"%@",msg);

// 4.设置循环播放
self.audioPlayer.numberOfLoops = -1;
self.audioPlayer.delegate = self;

// 5.开始播放
[self.audioplayer play];

二、使用System Sound Services播放音频

利用System Sound Services只能播放一些很小的提示或警告音频,它存在诸多限制,例如:声音长度不能超过30秒,不能控制进度,格式支持少等。

1. 注册音频文件

调用 AudioServicesCreateSystemSoundID(CFURLRef inFileURL,SystemSoundID *outSystemSoundID) 该函数的第一个参数代表音频文件的URL(可通过NSURL转换成CFURLRef),第二个参数代表注册音频文件的SystemSoundID。

2. 在音频播放完执行某些操作

调用AudioServicesAddSystemSoundCompletion()函数为制定SystemSoundID注册Callback函数。

3. 播放音频

调用AudioServicePlaySystemSound函数或者AudioServicePlayAlertSound(调用系统振动功能)。

4. 实战

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#import "FKViewController.h"
static void completionCallback(SystemSoundID mySSID)
{
// Play again after sound play completion
AudioServicesPlaySystemSound(mySSID);
}
@implementation ViewController
// 音频文件的ID
SystemSoundID ditaVoice;

- (void)viewDidLoad
{
[super viewDidLoad];
// 1. 定义要播放的音频文件的URL
NSURL *voiceURL = [[NSBundle mainBundle]URLForResource:@"CleanDidFinish" withExtension:@"aiff"];

// 2. 注册音频文件(第一个参数是音频文件的URL 第二个参数是音频文件的SystemSoundID)
AudioServicesCreateSystemSoundID((__bridge CFURLRef)(voiceURL),&ditaVoice);

// 3. 为crash播放完成绑定回调函数
AudioServicesAddSystemSoundCompletion(ditaVoice,NULL,NULL,(void*)completionCallback,NULL);

// 4. 播放 ditaVoice 注册的音频 并控制手机震动
AudioServicesPlayAlertSound(ditaVoice);

// AudioServicesPlaySystemSound(ditaVoice);
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); // 控制手机振动
}

使用System Sound Services需要AudioToolbox框架的支持,需要导入其主头文件:#import<AudioToolbox/AudioToolbox.h>


三、使用MPMusicPlayerController控制本机音乐播放

对控制内置音乐库播放状态以及媒体信息的获取进行了封装,主要用于公司手环端蓝牙发送指令控制手机音乐播放以及在手环荧幕上显示歌曲名称。
下面介绍一下用法:

  1. 包含我封装的头文件 #import "BackgroundMusic.h"
  2. 遵守协议:achieveMusicInfoDelegate
  3. 初始化:
1
@property (nonatomic,strong) BackgroundMusic *musicController;
self.musicController = [[BackgroundMusic alloc]init];
self.musicController.delegate = self; // 设置当前控制器为代理

4. 监听媒体曲目的改变:

1
// 在 - (void)viewDidLoad 方法中调用以下方面
[self.musicController monitorMediaItem];

// 实现代理方法
- (void)achieveachieveMusicInfo:(NSString *)songName andPlaybackStatus:(int)playStatus
{
if (1 == playStatus) {
NSLog(@"正在播放音乐中...");
}else if(0 == playStatus){
NSLog(@"音乐暂停中...");
}else{
NSLog(@"播放状态未知...");
}

NSLog(@"歌曲信息:%@",songName);
}

5. 播放控制

1
// 控制音乐播放、暂停
[self playOrPause];

// 下一曲
[self next];

  • 使用MPMusicPlayerController实例化对象来播放内置音乐库的媒体文件,有以下两种类方法来实例化对象:
  • MPMusicPlayerController *playController = [MPMusicPlayerController systemMusicPlayer];
    说明:播放内置媒体库项目取代用户目前播放状态(如果是用网易云音乐或QQQ音乐在播放歌曲)
  • MPMusicPlayerController *playController = [MPMusicPlayerController applicationMusicPlayer];
    说明:播放该应用内的歌曲,不影响本机自带音乐播放器的状态。

1. 判断有没有正在播放的媒体项目

  • 返回NSNotFound表示empty queue or an infinite playlist
1
if ([self.playController indexOfNowPlayingItem] == NSNotFound) {
return YES;
}else{
return NO;
}

2. 创建媒体队列

  • 根据query创建媒体队列,创建成功后可以条用play来播放(默认播放第 index = 0 首曲目)
1
/**
*  设置媒体播放队列
*/
- (void)createMediaQuery
{
// Creates a media query that matches music items and that groups and sorts collections by song name.
self.query = [MPMediaQuery songsQuery];

// Sets a music player’s playback queue based on a media query.
[self.playController setQueueWithQuery:self.query];
}

3. 获取正在播放的媒体曲目的信息

  • 可以由nowPlayingItem取得一系列正在播放的曲目的详细信息:
    1
    @property (nonatomic, readonly) MPMediaEntityPersistentID 
    @property (nonatomic, readonly) MPMediaType mediaType 
    @property (nonatomic, readonly) NSString *title 
    @property (nonatomic, readonly) NSString *albumTitle 
    @property (nonatomic, readonly) MPMediaEntityPersistentID 
    @property (nonatomic, readonly) NSString *artist 
    @property (nonatomic, readonly) MPMediaEntityPersistentID 
    @property (nonatomic, readonly) NSString *albumArtist 
    ...
1
/**
*  获取媒体信息
*/
- (void)obtainMusicInfo
{
MPMediaItem *currentItem = [self.playController nowPlayingItem];
NSString *artist = [currentItem valueForProperty:MPMediaItemPropertyArtist];
NSString *songName = [currentItem valueForProperty:MPMediaItemPropertyTitle];

self.musicInfo = [NSString stringWithFormat:@"%@-%@",artist,songName];
}

4. 监听播放媒体项目的通知

  • 监听此通知可以在播放曲目发生改变时(如:下一曲、上一曲)作出动作。
1
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(updateMusicInfo)
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:nil];

[self.playController beginGeneratingPlaybackNotifications];
坚持原创技术分享,您的支持将鼓励我继续创作!