在前面一篇中的七個步驟之前我們還得知道AudioSession個問題。
本片就先講AudioSession的使用和一些需要注意的地方。
1、AudioSession概述
AudioSession主要作用有一下幾點:
- 設置自己的APP是否和其他APP音頻同時存在,還是中斷其他APP聲音
- 在手機調到靜音模式下,自己的APP音頻是否可以播放出聲音
- 電話或者其他APP中斷自己APP的音頻的事件處理
- 指定音頻輸入和輸出的設備(比如是聽筒輸出聲音,還是揚聲器輸出聲音)
- 是否支持錄音,錄音同時是否支持音頻播放
AudioSession相關的類有兩個
AudioToolbox中的AudioSession。
AVFoundation中的AVAudioSession。
AudioSession在SDK7中已經被標注為depracated了,而AVAudioSession這個類雖然iOS 3開始就已經存在了,但其中很多方法和變量都是在iOS 6以后甚至是iOS 7才有的。所以各位可以依照以下標準選擇:
- 如果最低版本支持iOS 5,可以使用AudioSession,也可以使用AVAudioSession;
- 如果最低版本支持iOS 6及以上,請使用AVAudioSession
現在應該很少有需要支持iOS 5的了吧,我就以AVAudioSession為例吧.
// AVAudioSession是一個到單例
AVAudioSession *audiosession = [AVAudioSession sharedInstance];
// AVAudioSessionCategorySoloAmbient系統默認的
[audiosession setCategory:AVAudioSessionCategorySoloAmbient error:nil];
// 激活AVAudioSession
[audiosession setActive:YES error:nil];
Category目前有七種,其中對應了是否支持一下四種能力:
- Interrupts non-mixable apps audio:是否打斷不支持混音播放的APP
- Silenced by the Silent switch:是否會響應手機靜音鍵開關
- Supports audio input:是否支持音頻錄制
- Supports audio output:是否支持音頻播放
Category | 是否允許音頻播放/錄音 | 是否打斷其他不支持混音APP | 是否會被靜音鍵或鎖屏鍵靜音 |
---|---|---|---|
AVAudioSessionCategoryAmbient | 只支持播放 | 否 | 是 |
AVAudioSessionCategoryAudioProcessing | 不支持播放,不支持錄制 | 是 | 否 |
AVAudioSessionCategoryMultiRoute | 支持播放,支持錄制 | 是 | 否 |
AVAudioSessionCategoryPlayAndRecord | 支持播放,支持錄制 | 默認YES,可以重寫為NO | 否 |
AVAudioSessionCategoryPlayback | 只支持播放 | 默認YES,可以重寫為NO | 否 |
AVAudioSessionCategoryRecord | 只支持錄制 | 是 | 否(鎖屏下仍可錄制) |
AVAudioSessionCategorySoloAmbient | 只支持播放 | 是 | 是 |
我們也可以通過AVAudioSession的屬性來讀取當前設備支持的Category
@property(readonly) NSArray<NSString *> *availableCategories;
這樣可以保證設備的兼容性
設置Category的代碼示例如下:
NSError *setCategoryError = nil;
BOOL isSuccess = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
if (!success) {
//這里可以讀取setCategoryError.localizedDescription查看錯誤原因
}
AVAudioSession Mode&&Options
剛剛介紹的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));
// 也可以通過屬性來讀取
@property(readonly) NSArray<NSString *> *availableModes;
有七種mode來定制我們的Category行為:
1、 AVAudioSessionModeDefault:默認模式,與所有的 Category 兼容。
2、 AVAudioSessionModeVoiceChat:只有與AVAudioSessionCategoryPlayAndRecord有效。適用于IP語音。(VoIP)應用程序。減少允許的音頻路由的數量。這適用于VoIP應用程序,并可采用適當的系統提供。信號處理。是否設置了AVAudioSessionCategoryOptionAllowBluetooth?
3、 AVAudioSessionModeGameChat:由Game Kit代表使用GKVoiceChat對象的應用程序設置;有效的只有AVAudioSessionCategoryPlayAndRecord類別。不要直接設置此模式。如果你需要類似的行為并且不使用。
一個GKVoiceChat對象,使用AVAudioSessionModeVoiceChat代替。
4、 AVAudioSessionModeVideoRecording:只對AVAudioSessionCategoryPlayAndRecord/AVAudioSessionCategoryRecord有效。修改音頻路由選項,并可能參與適當的系統提供的信號處理。
5、AVAudioSessionModeMeasurement:適用于希望最小化系統提供的信號效果的應用程序。處理輸入和/或輸出音頻信號。
6、AVAudioSessionModeMoviePlayback:對電影播放場景進行適當的輸出信號處理。目前只在播放時使用內置揚聲器。
7、AVAudioSessionModeVideoChat:用于視頻聊天類型應用,只能是 AVAudioSessionCategoryPlayAndRecord Category下。適在這個模式系統會自動配置 AVAudioSessionCategoryOptionAllowBluetooth 和 AVAudioSessionCategoryOptionDefaultToSpeaker 選項。系統會自動選擇最佳的內置麥克風組合支持視頻聊天。
AVAudioSession Options
1、AVAudioSessionCategoryOptionMixWithOthers:支持和其他APP音頻 mix
2、AVAudioSessionCategoryOptionDuckOthers:系統智能調低其他APP音頻音量
3、AVAudioSessionCategoryOptionAllowBluetooth:支持藍牙音頻輸入
4、AVAudioSessionCategoryOptionDefaultToSpeaker:設置默認輸出音頻到揚聲器
通過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
音頻中斷處理
其他APP或者電話會中斷我們的APP音頻,所以相應的我們要做出處理。
我們可以通過監聽AVAudioSessionInterruptionNotification和AVAudioSessionSilenceSecondaryAudioHintNotification兩個key獲取音頻中斷事件
AVAudioSessionInterruptionNotification監聽電話、鬧鈴等一般性的中斷
回調回來Userinfo有兩個鍵值
AVAudioSessionInterruptionTypeKey:
取值AVAudioSessionInterruptionTypeBegan表示中斷開始
取值AVAudioSessionInterruptionTypeEnded表示中斷結束AVAudioSessionInterruptionOptionKey:
取值AVAudioSessionInterruptionOptionShouldResume表示可以恢復播放
AVAudioSessionSilenceSecondaryAudioHintNotification監聽其他APP占據AudioSession,回調回來Userinfo有一個鍵值AVAudioSessionSilenceSecondaryAudioHintTypeKey:
取值AVAudioSessionSilenceSecondaryAudioHintTypeBegin表示中斷開始
取值AVAudioSessionSilenceSecondaryAudioHintTypeEnd表示中斷結束
中斷開始:我們需要做的是保存好播放狀態,上下文,更新用戶界面等
中斷結束:我們要做的是恢復好狀態和上下文,更新用戶界面,根據需求準備好之后選擇是否激活我們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。
需要注意的是:
- 有中斷開始事件,不一定對應有中斷結束事件,所以需要在用戶進入前臺,點擊UI操作的時候,需要保存好播放狀態和對Audio Session管理,以便不影響APP的音頻功能。
2.音頻資源競爭上,一定是電話優先。
- AVAudioSession同樣可以監聽外設音頻狀態,比如耳機拔入拔出。這里不做累述