蘋果系統(tǒng)帶有一個(gè)音頻播放器,這就是AVAudioPlayer级野,要使用這個(gè)播放器進(jìn)行播放音頻棒厘,首先需要?jiǎng)?chuàng)建這個(gè)播放器對(duì)象,而這個(gè)播放器的創(chuàng)建所需的頭文件并不是在foundation的頭文件下而是在播放器自己專屬的頭文件下如迟,如下:
#import <AVFoundation/AVFoundation.h>
而AV開頭的文件里包含了許多的和音視頻相關(guān)的頭文件收毫。
一、創(chuàng)建播放器對(duì)象
我們先聲明一個(gè)播放器的全局變量殷勘,而且只能聲明稱全局變量此再。
AVAudioPlayer *_audioPlayer;
此時(shí)我們創(chuàng)建播放器對(duì)象:
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
這里有兩個(gè)參數(shù):
參數(shù)1:需要播放的音頻的地址,這里可以是本地或者是網(wǎng)頁的文件
參數(shù)2:錯(cuò)誤信息
這里就暫且使用本地資源玲销,需要?jiǎng)?chuàng)建本地資源的路徑输拇,然后轉(zhuǎn)為url路徑
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:nil];
這里有兩個(gè)參數(shù):
參數(shù)1:文件的名字
參數(shù)2:文件的類型
注意的是:在參數(shù)1中如果包含了名字和類型,在參數(shù)2中可以不用謝類型贤斜,直接寫nil就可以了策吠。
然后將string類型的路徑用url來接收
NSURL *url = [NSURL fileURLWithPath:path];
這里的參數(shù)就是之前創(chuàng)建的NSString類型的路徑。
完整的代碼如下:
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
_audioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];
二瘩绒、播放
音頻播放之前需要準(zhǔn)備播放猴抹,這里需要調(diào)用一個(gè)方法;
[_audioPlayer prepareToPlay];
就緒后直接播放
[_audioPlayer play];
以上就是和音頻最主要的功能的介紹锁荔。
三蟀给、音頻播放器的相關(guān)功能
下面是對(duì)音頻播放器的擴(kuò)展,音頻播放器一般會(huì)有的功能如:開始播放阳堕、暫停播放坤溃、調(diào)整音頻的音量的大小、調(diào)整音頻的進(jìn)度嘱丢、顯示音頻文件的內(nèi)部附有的圖片信息及協(xié)議代理等薪介。
1.開始和暫停播放音頻
首先,為了方便越驻,我們?cè)趕toryBoard去拖一個(gè)按鈕控件汁政,主要功能是讓音頻暫停和播放道偷。
這里我們可以用到自動(dòng)布局的相關(guān)知識(shí),在storyBoard里運(yùn)用約束條件记劈,使得可以進(jìn)行適配手機(jī)勺鸦。這里對(duì)按鈕的左右下和高度進(jìn)行約束。
讓按鈕的初始文字顯示為播放
目木,點(diǎn)擊播放
后,顯示為STOP
,暫停后顯示為play
换途;隨便設(shè)個(gè)背景顏色用于區(qū)分
然后直接在storyBoard里面拖個(gè)方法到ViewController.m文件的@implementation里,然后就在這里這個(gè)按鈕的點(diǎn)擊事件里執(zhí)行音頻的播放和暫停
代碼如下:
#pragma mark - 開始暫停按鈕
- (IBAction)button:(UIButton *)sender {
// 用一個(gè)靜態(tài)變量對(duì)按鈕的狀態(tài)進(jìn)行控制
static int i = 0;
if (i == 0) {
// 開始播放
[_audioPlayer play];
// 開始后按鈕文字變?yōu)閟top刽射,按鈕的狀態(tài)為正常
[sender setTitle:@"stop" forState:UIControlStateNormal];
i = 1;
}
else {
// 4.暫停播放
[_audioPlayer pause];
//[_audioPlayer stop];
[sender setTitle:@"play" forState:UIControlStateNormal];
i = 0;
}
}
2.調(diào)整音量大小
我們還是可以在storyBoard中拖一個(gè)控件出來军拟,這里需要一個(gè)步進(jìn)器,然后把相關(guān)的方法拖到文件中去實(shí)現(xiàn)誓禁。
#pragma mark - 改變音量
- (IBAction)volumeChange:(UIStepper *)sender {
// 設(shè)置音量(0 ~ 1);我們?cè)O(shè)置的步進(jìn)的音量值為0.1
_audioPlayer.volume = sender.value;
}
3.調(diào)整音頻播放進(jìn)度
3.1更新進(jìn)度
調(diào)整進(jìn)度就需要用到滑塊控件懈息,然后向之前的在storyBoard里去拖個(gè)滑塊的控件,還有相關(guān)的屬性和方法摹恰。
這里我們可能會(huì)運(yùn)用到定時(shí)器辫继,所以我們需要?jiǎng)?chuàng)建定時(shí)器,而這個(gè)定時(shí)器的創(chuàng)建應(yīng)該放到準(zhǔn)備播放音頻的時(shí)候就創(chuàng)建出來俗慈。
// 添加定時(shí)器
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
這里的參數(shù)為:
參數(shù)1:定時(shí)器的監(jiān)測(cè)時(shí)間姑宽,單位是S
參數(shù)2:執(zhí)行的對(duì)象
參數(shù)3:選擇器(需要執(zhí)行的方法)
參數(shù)4:用戶的信息,一般為nil
參數(shù)5:是否需要重復(fù)執(zhí)行闺阱,這里是需要的低千,為YES
實(shí)現(xiàn)選擇器中的方法;
#pragma mark - 更新進(jìn)度updateProgress
- (void)updateProgress {
// 當(dāng)前時(shí)間
double currentTime = _audioPlayer.currentTime;
// 總時(shí)間
double totalTime = _audioPlayer.duration;
// 計(jì)算進(jìn)度
float progress = currentTime / totalTime;
// 展示到進(jìn)度條上
self.sliderProgress.value = progress;
}
3.2更改滑塊的進(jìn)度
這里就需要實(shí)現(xiàn)滑塊拖出來的方法了
#pragma mark - 改變進(jìn)度條
- (IBAction)sliderProgress:(UISlider *)sender {
// 當(dāng)前時(shí)間 = 總時(shí)間 * 爆發(fā)進(jìn)度
double currentTime = _audioPlayer.duration * _sliderProgress.value;
// 是否讓進(jìn)度條實(shí)時(shí)更新馏颂。
_sliderProgress.continuous = YES;
// 重新設(shè)置播放器的當(dāng)前時(shí)間
_audioPlayer.currentTime = currentTime;
}
4.獲取專輯的圖片
同樣的需要在storyBoard上拖一個(gè)imageView的控件示血,展示出其屬性。
#pragma mark - 獲取專輯圖片
- (void)showPlayerImage {
AVURLAsset *asset = [[AVURLAsset alloc]initWithURL:_audioPlayer.url options:nil];
NSString *format = [asset availableMetadataFormats].firstObject;
NSArray *array = [asset metadataForFormat:format];
for (AVMutableMetadataItem *item in array) {
// 這里的artwork是需要在音頻文件里去得到的救拉∧焉螅可以吧array打印出來,得到里面的值
if ([item.commonKey isEqualToString:@"artwork"]) {
NSData *data = (NSData *)item.value;
UIImage *image = [UIImage imageWithData:data];
_imageView.image = image;
}
}
}
5.協(xié)議代理
5.1當(dāng)前音頻播放器播放的音頻結(jié)束后會(huì)自動(dòng)調(diào)用這個(gè)方法
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
NSLog(@"播放結(jié)束");
// 切換下一首
[self preparePlayerWithName:@"春天里.mp3"];
[_audioPlayer play];
}
5.2音頻播放被中斷的時(shí)候會(huì)調(diào)用這個(gè)方法
一般有電話的接入和有短信接收的時(shí)候亿絮,一般會(huì)有中斷告喊,這需要調(diào)用這個(gè)方法。我們一般執(zhí)行的都是暫停音頻的播放派昧。
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player {
NSLog(@"一般這個(gè)方法中會(huì)暫停音頻");
[player stop];
}
5.3中斷結(jié)束后
一般就在來電結(jié)束后會(huì)調(diào)用這個(gè)方法黔姜。一般在這個(gè)方法中執(zhí)行的是會(huì)繼續(xù)音頻的播放。
// 中斷結(jié)束的時(shí)候會(huì)調(diào)用這個(gè)方法
- (void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flags {
// 一般在這個(gè)方法中繼續(xù)播放音頻
[player play];
NSLog(@"繼續(xù)播放");
}
5.4解碼出錯(cuò)
// 解碼錯(cuò)誤的時(shí)候會(huì)調(diào)用這個(gè)方法
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error {
NSLog(@"文件出錯(cuò)");
}
總結(jié):
1.這里需要導(dǎo)入的頭文件一定是:AVFoundation/AVFoundation.h蒂萎;
2.音頻播放器AVAudioPlayer作為一個(gè)對(duì)象秆吵,要使用必須要先創(chuàng)建對(duì)象,創(chuàng)建對(duì)象前需要給一個(gè)音頻文件的路徑(一般都是url)五慈;
3.聲明對(duì)象一定是要全局變量纳寂,不然運(yùn)行可能失敗主穗,因?yàn)闀?huì)調(diào)用到偏硬件的;
4.就是在storyBoard里拖控件的時(shí)候需要注意自動(dòng)布局的約束條件毙芜,為的是適配忽媒;
5.在有代理的設(shè)置的時(shí)候,一定要遵循代理:AVAudioPlayerDelegate腋粥。