iOS開發(fā)-AVAudioPlayer

簡述

AVAudioPlayer 是一個屬于 AVFoundation.framework 的一個類,它的功能類似于一個功能強大的播放器,AVAudioPlayer 支持廣泛的音頻格式,主要是以下這些格式。

  • AAC
  • AMR (Adaptive multi-Rate,一種語音格式)
  • ALAC (Apple lossless Audio Codec)
  • iLBC (internet Low Bitrate Codec,另一種語音格式)
  • IMA4 (IMA/ADPCM)
  • linearPCM (uncompressed)
  • u-law 和 a-law
  • MP3 (MPEG-Laudio Layer 3)

AVAudioPlayer 的使用

AVAudioPlayer 初始化

  1. initWithContentsOfURL: error: 從URL加載音頻,返回 AVAudioPlayer 對象
  2. initWithData: error: 加載NSdata對象的音頻文件,返回 AVAudioPlayer 對象

AVAudioPlayer方法調(diào)用

  1. - (BOOL)play 開始或恢復(fù)播放,調(diào)用該方法時,如果該音頻還沒有準備好,程序會隱士執(zhí)行 - (BOOL)prepareToPlay 方法
  2. - (void)pause 暫停
  3. - (void)stop 停止
  4. - (BOOL)playAtTime:(NSTimeInterval)time NS_AVAILABLE(10_7, 4_0) 在某個時間點播放
  5. - (BOOL)prepareToPlay 準備開始播放
  6. - (void)updateMeters 更新音頻測量值,注意如果要更新音頻測量值必須設(shè)置meteringEnabled為YES,通過音頻測量值可以即時獲得音頻分貝等信息
  7. - (float)averagePowerForChannel:(NSUInteger)channelNumber 獲得指定聲道的分貝峰值,注意如果要獲得分貝峰值必須在此之前調(diào)用updateMeters方法

使用 AVAudioPlayer 讀取音頻信息

  1. volume 播放器的音頻增益,值:0.0~1.0
  2. pan NS_AVAILABLE(10_7, 4_0) 立體聲設(shè)置 設(shè)為 -1.0 則左邊播放 設(shè)為 0.0 則中央播放 設(shè)為 1.0 則右邊播放
  3. enableRate 是否允許改變播放速率
  4. rate NS_AVAILABLE(10_8, 5_0) 播放速率 0.5 (半速播放) ~ 2.0(倍速播放) 注1.0 是正常速度
  5. playing 是否正在播放音頻
  6. numberOfLoops 循環(huán)次數(shù),如果要單曲循環(huán),設(shè)置為負數(shù)
  7. numberOfChannels 該音頻的聲道次數(shù) (只讀)
  8. duration 該音頻時長
  9. currentTime 該音頻的播放點
  10. deviceCurrentTime 輸出設(shè)備播放音頻的時間,注意如果播放中被暫停此時間也會繼續(xù)累加
  11. url 音頻文件路徑,只讀
  12. data 音頻數(shù)據(jù),只讀
  13. channelAssignments 獲得或設(shè)置播放聲道

代理方法

  1. - (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag; 音頻播放完成
  2. - (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError * __nullable)error 音頻解碼發(fā)生錯誤
  3. - (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player 如果音頻被中斷,比如有電話呼入,該方法就會被回調(diào),該方法可以保存當前播放信息,以便恢復(fù)繼續(xù)播放的進度

代碼

AVAudioPlayer 初始化

首先導(dǎo)入兩首格式為 mp3 的歌曲,再導(dǎo)入歌手圖片

在 ViewController.h 導(dǎo)入

#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

然后必須持有一個 AVAudioPlayer 對象,若此對象不是屬性,則無法播放

@property (nonatomic , strong) AVAudioPlayer *player;

添加控件如圖所示,給控件命名

storyboard
storyboard

獲取制定 url 對象

NSURL *url = [[NSBundle mainBundle] URLForResource:@"吳亦凡-時間煮雨" withExtension:@"mp3"];

初始化 AVAudioPlayer 對象

self.player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];

設(shè)置代理

self.player.delegate = self;

這樣就播放器就初始化完成了

將storyboard里面 開始 按鈕綁定 - (IBAction)start:(id)sender 方法

- (IBAction)start:(id)sender {
    
    if ([self.player isPlaying]) {
        [self.startBtn setBackgroundImage:[UIImage imageNamed:@"播放"] forState:0];
        [self.player pause];
    }
    else
    {
        [self.startBtn setBackgroundImage:[UIImage imageNamed:@"暫停"] forState:0];
        [self.player play];
    }
    
    if (_timer == nil) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateProgress) userInfo:nil repeats:YES];
    }
    
}

注: 上訴代碼中定義了一個 NSTimer 變量,因為播放器沒有播放進程的委托,所以只能自定義NSTimer變量對播放器進行監(jiān)控

@property (strong, nonatomic) NSTimer *timer;

將storyboard里面 停止 按鈕綁定 - (IBAction)stop:(id)sender 方法

- (IBAction)stop:(id)sender {
    [self.player stop];
    //計時器停止
    [_timer invalidate];
    //釋放定時器
    _timer = nil;
}

設(shè)置剛才綁定的定時器調(diào)用方法updateProgress

-(void)updateProgress{
    //進度條顯示播放進度
    self.progress.progress = self.player.currentTime/self.player.duration;
    self.info1.text = [NSString stringWithFormat:@"當前播放時間%f",self.player.currentTime];
}

實現(xiàn) AVAudioPlayer 的委托方法

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag{
    
    if (player == _player && flag) {
        [self.startBtn setBackgroundImage:[UIImage imageNamed:@"播放"] forState:0];
    }
}
-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player{
    if (player == _player){
        NSLog(@"播放被中斷");
    }
}

此時,音樂就可以播放了!??!

但是,人們使用音樂大都是后臺播放,那么如何添加后臺播放支持呢?

后臺播放

在項目里 info.plist 右鍵 open As -- source code 添加代碼:

<key>UIBackgroundModes</key>
    <array>
        <string>audio</string>
    </array>

同樣,代碼里面也要添加后臺播放支持

//設(shè)置鎖屏仍能繼續(xù)播放
[[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];

這樣 音樂在后臺就可以播放了!!

那么很多播放器都有一個功能,那就是在用戶拔掉耳機的時候,暫停播放

監(jiān)聽播放設(shè)備

//添加通知,拔出耳機后暫停播放
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(routeChange:) name:AVAudioSessionRouteChangeNotification object:nil];
    
/**
 *  一旦輸出改變則執(zhí)行此方法
 *
 *  @param notification 輸出改變通知對象
 */
-(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];
        //原設(shè)備為耳機則暫停
        if ([portDescription.portType isEqualToString:@"Headphones"]) {
            [self.player pause];
        }
    }
}

這樣就能在拔掉耳機的時候,暫停播放了?。。?/p>

但是似乎還是差了一些什么,好像鎖屏界面空空如也?。。?!

定制鎖屏界面

設(shè)置后臺播放時顯示的東西,例如歌曲名字,圖片等

要用到 <MediaPlayer/MediaPlayer.h> 這個庫,剛才已經(jīng)導(dǎo)入過

- (void)setPlayingInfo {
    //    設(shè)置后臺播放時顯示的東西,例如歌曲名字,圖片等
    MPMediaItemArtwork *artWork = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"吳亦凡.jpg"]];
    
    NSDictionary *dic = @{MPMediaItemPropertyTitle:@"時間煮雨",
                          MPMediaItemPropertyArtist:@"吳亦凡",
                          MPMediaItemPropertyArtwork:artWork
                          };
    [[MPNowPlayingInfoCenter defaultCenter] setNowPlayingInfo:dic];
}

這樣,圖片就在鎖屏界面顯示了,不過,鎖屏界面上面的三個按鈕,怎么控制播放呢?。?/p>

接收鎖屏歌曲按鈕控制 (上一首,播放,下一首)

首先,你要在一個繼承 UIResponder 類里面接收遠程控制,本文以 ViewController 為例

添加如下代碼,接受遠程控制和取消遠程控制。

- (void)viewDidAppear:(BOOL)animated {
    //    接受遠程控制
    [self becomeFirstResponder];
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
}

- (void)viewDidDisappear:(BOOL)animated {
    //    取消遠程控制
    [self resignFirstResponder];
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
}

接收方法設(shè)置

- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
    if (event.type == UIEventTypeRemoteControl) {  //判斷是否為遠程控制
        switch (event.subtype) {
            case  UIEventSubtypeRemoteControlPlay:
                if (![_player isPlaying]) {
                    [_player play];
                }
                break;
            case UIEventSubtypeRemoteControlPause:
                if ([_player isPlaying]) {
                    [_player pause];
                }
                break;
            case UIEventSubtypeRemoteControlNextTrack:
                NSLog(@"下一首");
                break;
            case UIEventSubtypeRemoteControlPreviousTrack:
                NSLog(@"上一首 ");
                break;
            default:
                break;
        }
    }
}

效果圖:

播放頁面
播放頁面

鎖屏頁面
鎖屏頁面

這樣,播放器的基本功能就已經(jīng)完成 ?。? 代碼多有不祥之處,時間匆忙,敬請諒解,不實之處,請多包涵!!

Demo地址:
點此下載

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容