最近一年一直在作IPC Camera的iOS客戶端開發。和音頻打交道,必需要弄清楚 AVAudioSession。 先看下蘋果的官方圖: html
能夠看到AVAudioSession就是用來管理多個APP對音頻硬件設備(麥克風,揚聲器)的資源使用。ios
舉例一下AVAudioSession能夠作這些事情bash
AVAudioSession的接口比較簡單。APP啓動的時候會自動幫激活AVAudioSession,固然咱們能夠手動激活代碼以下。session
//導入頭文件
#import <AVFoundation/AVFoundation.h>
//AVAudioSession是一個單例類
AVAudioSession *session = [AVAudioSession sharedInstance];
//AVAudioSessionCategorySoloAmbient是系統默認的category
[session setCategory:AVAudioSessionCategorySoloAmbient error:nil];
//激活AVAudioSession
[session setActive:YES error:nil];
複製代碼
能夠看到設置session這裏有兩個參數,category和options Category iOS下目前有七種,每種Category都對應是否支持下面四種能力app
下面用圖表來直觀的看下每種category具體的能力集ide
Category | 是否容許音頻播放/錄音 | 是否打斷其餘不支持混音APP | 是否會被靜音鍵或鎖屏鍵靜音 |
---|---|---|---|
AVAudioSessionCategoryAmbient | 只支持播放 | 否 | 是 |
AVAudioSessionCategoryAudioProcessing | 不支持播放,不支持錄製 | 是 | 否 |
AVAudioSessionCategoryMultiRoute | 支持播放,支持錄製 | 是 | 否 |
AVAudioSessionCategoryPlayAndRecord | 支持播放,支持錄製 | 默認YES,能夠重寫爲NO | 否 |
AVAudioSessionCategoryPlayback | 只支持播放 | 默認YES,能夠重寫爲NO | 否 |
AVAudioSessionCategoryRecord | 只支持錄製 | 是 | 否(鎖屏下仍可錄製) |
AVAudioSessionCategorySoloAmbient | 只支持播放 | 是 | 是 |
AVAudioSessionCategoryAmbient,只支持音頻播放。這個 Category,音頻會被靜音鍵和鎖屏鍵靜音。而且不會打斷其餘應用的音頻播放。ui
AVAudioSessionCategorySoloAmbient,這個是系統默認使用的 Category,只支持音頻播放。音頻會被靜音鍵和鎖屏鍵靜音。和AVAudioSessionCategoryAmbient不一樣的是,這個會打斷其餘應用的音頻播放spa
AVAudioSessionCategoryPlayback,只支持音頻播放。你的音頻不會被靜音鍵和鎖屏鍵靜音。適用於音頻是主要功能的APP,像網易雲這些音樂app,鎖屏後依然能夠播放。code
須要注意一下,選擇支持在靜音鍵切到靜音狀態以及鎖屏鍵切到鎖屏狀態下仍然能夠播放音頻 Category 時,必須在應用中開啓支持後臺音頻功能,詳見 UIBackgroundModes。cdn
咱們也能夠經過AVAudioSession的屬性來讀取當前設備支持的Category
@property(readonly) NSArray<NSString *> *availableCategories;
複製代碼
這樣能夠保證設備兼容性。
設置Category的代碼示例以下
NSError *setCategoryError = nil;
BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
if (!success) {
//這裏能夠讀取setCategoryError.localizedDescription查看錯誤緣由
}
複製代碼
剛剛介紹的Category定義了七種主場景,實際開發需求中有時候須要對Category進行微調整,咱們發現這個接口還有兩個參數Mode和Options。
/* set session category and mode with options */
- (BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError API_AVAILABLE(ios(10.0), watchos(3.0), tvos(10.0));
複製代碼
咱們經過讀取下面這條屬性獲取當前設備支持的Mode
@property(readonly) NSArray<NSString *> *availableModes;
複製代碼
iOS下有七種mode來定製咱們的Category行爲
模式 | 兼容的 Category | 場景 |
---|---|---|
AVAudioSessionModeDefault | All | 默認模式 |
AVAudioSessionModeVoiceChat | AVAudioSessionCategoryPlayAndRecord | VoIP |
AVAudioSessionModeGameChat | AVAudioSessionCategoryPlayAndRecord | 遊戲錄製,GKVoiceChat自動設置 |
AVAudioSessionModeVideoRecording | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord | 錄製視頻 |
AVAudioSessionModeMoviePlayback | AVAudioSessionCategoryPlayback | 視頻播放 |
AVAudioSessionModeMeasurement | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback | 最小系統 |
AVAudioSessionModeVideoChat | AVAudioSessionCategoryPlayAndRecord | 視頻通話 |
下面逐一介紹下每一個Mode
AVAudioSessionModeDefault,默認模式,與全部的 Category 兼容
AVAudioSessionModeVoiceChat,適用於VoIP 類型的應用。只能是 AVAudioSessionCategoryPlayAndRecord Category下。在這個模式系統會自動配置AVAudioSessionCategoryOptionAllowBluetooth 這個選項。系統會自動選擇最佳的內置麥克風組合支持語音聊天。
AVAudioSessionModeVideoChat,用於視頻聊天類型應用,只能是 AVAudioSessionCategoryPlayAndRecord Category下。適在這個模式系統會自動配置 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 選項。系統會自動選擇最佳的內置麥克風組合支持視頻聊天。
AVAudioSessionModeGameChat,適用於遊戲類應用。使用 GKVoiceChat 對象的應用會自動設置這個模式和 AVAudioSessionCategoryPlayAndRecord Category。實際參數和AVAudioSessionModeVideoChat一致
AVAudioSessionModeVideoRecording,適用於使用攝像頭採集視頻的應用。只能是 AVAudioSessionCategoryPlayAndRecord 和 AVAudioSessionCategoryRecord 這兩個 Category下。這個模式搭配 AVCaptureSession API 結合來用能夠更好地控制音視頻的輸入輸出路徑。(例如,設置 automaticallyConfiguresApplicationAudioSession 屬性,系統會自動選擇最佳輸出路徑。
AVAudioSessionModeMeasurement,最小化系統。只用於 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryRecord、AVAudioSessionCategoryPlayback 這幾種 Category。
AVAudioSessionModeMoviePlayback,適用於播放視頻的應用。只用於 AVAudioSessionCategoryPlayback 這個Category。
咱們還可使用options去微調Category行爲,以下表
Option | Option功能說明 | 兼容的 Category |
---|---|---|
AVAudioSessionCategoryOptionMixWithOthers | 支持和其餘APP音頻 mix | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute |
AVAudioSessionCategoryOptionDuckOthers | 系統智能調低其餘APP音頻音量 | AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryPlayback AVAudioSessionCategoryMultiRoute |
AVAudioSessionCategoryOptionAllowBluetooth | 支持藍牙音頻輸入 | AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayAndRecord |
AVAudioSessionCategoryOptionDefaultToSpeaker | 設置默認輸出音頻到揚聲器 | AVAudioSessionCategoryPlayAndRecord |
經過Category和合適的Mode和Options的搭配咱們能夠調優出咱們的效果,下面舉兩個應用場景:
用太高德地圖的都知道,在後臺播放QQ音樂的時候,若是導航語音出來,QQ音樂不會中止,而是被智能壓低和混音,等導航語音播報完後,QQ音樂正常播放,這裏咱們須要後臺播放音樂,因此Category使用AVAudioSessionCategoryPlayback,須要混音和智能壓低其餘APP音量,因此Options選用 AVAudioSessionCategoryOptionMixWithOthers和AVAudioSessionCategoryOptionDuckOthers
代碼示例以下
BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers | AVAudioSessionCategoryOptionDuckOthers error:&setCategoryError];
複製代碼
又或者我但願AVAudioSessionCategoryPlayAndRecord這個Category默認的音頻由揚聲器播放,那麼能夠調用這個接口去調整Category
- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
複製代碼
經過選擇合適和Category,mode和options,就能夠調優音頻的輸入輸出,來知足平常開發需求(須要注意的是Category,mode,option是搭配使用的,而不是簡單組合,也就是說某種Category支持某些mode和option,從上面的表中也能夠看出這一點)
其餘APP或者電話會中斷咱們的APP音頻,因此相應的咱們要作出處理。 咱們能夠經過監聽AVAudioSessionInterruptionNotification這個key獲取音頻中斷事件
回調回來Userinfo有鍵值
中斷開始:咱們須要作的是保存好播放狀態,上下文,更新用戶界面等 中斷結束:咱們要作的是恢復好狀態和上下文,更新用戶界面,根據需求準備好以後選擇是否激活咱們session。
選擇不一樣的音頻播放技術,處理中斷方式也有差異,具體以下:
System Sound Services:使用 System Sound Services 播發音頻,系統會自動處理,不受APP控制,當中斷髮生時,音頻播放會靜音,當中斷結束後,音頻播放會恢復。
AV Foundation framework:AVAudioPlayer 類和 AVAudioRecorder 類提供了中斷開始和結束的 Delegate 回調方法來處理中斷。中斷髮生,系統會自動中止播放,須要作的是記錄播放時間等狀態,更新用戶界面,等中斷結束後,再次調用播放方法,系統會自動激活session。
Audio Queue Services, I/O audio unit:使用aduio unit這些技術須要處理中斷,須要作的是記錄播放或者錄製的位置,中斷結束後本身恢復audio session。
OpenAL:使用 OpenAL 播放時,一樣須要本身監聽中斷。管理 OpenAL上下文,用戶中斷結束後恢復audio session。
須要注意的是:1. 有中斷開始事件,不必定對應有中斷結束事件,因此須要在用戶進入前臺,點擊UI操做的時候,須要保存好播放狀態和對Audio Session管理,以便不影響APP的音頻功能。2.音頻資源競爭上,必定是電話優先。3. AVAudioSession一樣能夠監聽外設音頻狀態,好比耳機拔入拔出。這裏不作累述
AVAudioSession的做用就是管理音頻這一惟一硬件資源的分配,經過調優合適的AVAudioSession來適配咱們的APP對於音頻的功能需求。切換音頻場景時候,須要相應的切換AVAudioSession。