本文轉自:AVAudioSession(2):定義一個 Audio Session | www.samirchen.com
本文內容主要來源于 Defining an Audio Session。
Audio Session 的默認行為
AVAudioSession 的默認行為如下:
- 音頻播放能力是開啟的,但是音頻錄制能力是關閉的。
- 當用戶通過靜音鍵切換到靜音模式時,你的音頻會被靜音。
- 當用戶通過鎖屏鍵鎖定屏幕或者自動鎖屏定時觸發時,你的音頻會被靜音。
- 當你的音頻開始播放時,正在播放的其他 App 的音頻會被靜音。
這些行為是由默認的 AVAudioSessionCategorySoloAmbient Category 設定的。通常默認設置是不能滿足你的需求的,除非你的 App 對音頻的控制場景如下:
- 你的 App 只使用 System Sound Services 或者 UIKit 中的 playInputClick 方法來處理音頻,而沒有用到其他音頻相關的 API 時。
- 你的 App 不使用任何音頻。
系統如何解決競爭性的音頻請求
流程大致如下圖,還是挺好理解的:
需要注意的是,系統永遠遵循一個原則:電話的優先級最高。
和 AVCaptureSession 協同
在 AV Foundatin capture 相關的 API 中(AVCaptureDevice, AVCaptureSession)允許你從攝像頭和麥克風采集同步的音視頻數據。其中表示麥克風的 AVCaptureDevice 對象可以共享你的 AVAudioSession。通常情況下,如果 AVCaptureSession 需要使用麥克風進行音頻錄制時,它會去修改優化你的 AVAudioSession 配置。如果你不希望這樣,則需要設置對應的 AVCaptureSession 對象的 automaticallyConfiguresApplicationAudioSession 屬性為 NO 來讓 AVCaptureSession 使用你當前的 AVAudioSession 配置而不會修改它。
初始化 Audio Session
代碼如下:
// implicitly initializes your audio session
AVAudioSession *session = [AVAudioSession sharedInstance];
音量和路徑控制
蘋果官方推薦使用 MPVolumeView 來控制音頻音量和路徑,MPVolumeView 提供了一個 Slider 來控制音量,提供了一個按鈕來供你選擇音頻輸出路徑。
你可以通過如下代碼來設置音頻輸出路徑到話筒:
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
但蘋果推薦你用 MPVolumeView 提供的路徑選擇按鈕來實現音頻輸出路徑切換。
響應遠程控制事件
通過響應 Remote Control Events 能讓你在播放音視頻內容時,可以響應來自鎖屏界面、外部設備等 App 外部的控制。
具體參見 Remote Control Events 和 MPNowPlayingInfoCenter Class Reference。
激活和關閉 Audio Session
蘋果官方建議如果你需要用到 Audio Session,總是應該顯示地激活你的 Audio Session。并且參考 Setting Preferred Hardware Values 來設置相應的硬件參數。這樣可以在你使用 Audio Session 前來測試是否能成功激活,以便于做出正確的處理邏輯。
激活 Audio Session 代碼如下:
NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive:YES error:&activationError]; // Pass 'NO' when deactivate your audio session.
if (!success) { /* handle the error in activationError */ }
值得注意的是,大部分時候我們不需要關閉 Audio Session,除非是在 VoIP(Voice over Internet Protocol) 類應用、turn-by-turn 導航類應用和某些錄制類應用中。這時你需要注意:
- 對于 VoIP 類應用,要確保 Audio Session 只在電話接聽中是 Active 的。當應用處于后臺時,保持應用為準備接聽電話的狀態,但應用的 Audio Session 應該是 Inactive 的。
- 對于定位于 Recording Category 來使用 Audio Session 的應用,要確保只在錄制中設置 Audio Session 為 Active 狀態,在錄制開始前和錄制結束后要確保 Audio Session 為 Inactive 狀態以允許其他音頻的播放。
檢查是否有其他音頻正在播放
你可以通過 otherAudioPlaying 來檢查是否當前有其他應用的音頻正在播放。
比如你是一個自帶音效的游戲,當一個正在聽音樂的用戶打開你的游戲時,iOS 設計指南會建議你不要關閉用戶正在聽的音樂而播放你的游戲音效,這時候你怎么處理呢?你可以用上面的接口檢查一下,如果有聲音在播放則將你的音效靜音并設置 AVAudioSessionCategorySoloAmbient。
Inter-App Audio 特性
Inter-App Audio 特性允許一個 Node App 將它的音頻輸出給一個 Host App。也可以由 Host App 發送它的音頻給 Node App 進行處理,處理完后再發回給 Host App。Host App 需要設置一個 Active 的 Audio Session,而 Node App 則只在從 Host App 或系統接收音頻輸入時才需要一個 Active 的 Audio Session。
你可以使用下面這些規則來搭建 Inter-App Audio:
- 為 Node App 和 Host App 都設置 「inter-app-audio」的 entitlement。
- 為 Host App 設置 UIBackgroundModes 的 audio flag。
- 為那些在與 Host App 連接時使用音頻輸入或輸出路徑的 Node App 設置 UIBackgroundModes 的 audio flag。
- 為 Node App 和 Host App 都設置 AVAudioSessionCategoryOptionMixWithOthers 這個 Category。
- 確保連接著 inter-app host 的 Node App 在接收來自系統的音頻或者輸出音頻時的 Audio Session 是 Active 的。