【IOS】Audio Session Programming Guide 翻譯 by kk(二)

定義一個(gè)音頻會(huì)話

音頻會(huì)話是 App 和 IOS 之間的媒介,用來為 App 配置相關(guān)的音頻屬性和行為。在加載過程中,App 會(huì)自動(dòng)創(chuàng)建一個(gè)音頻會(huì)話的單例。開發(fā)者可以通過配置音頻會(huì)話來描述 App 對(duì)音頻的需求。比如:

  • 在 App 播放聲音的時(shí)候,開發(fā)者是想讓其他 App 的聲音停止還是和自己的聲音混合在一起?
  • 當(dāng)碰到系統(tǒng)鬧鐘或其他聲音響起的時(shí)候,App 中的聲音會(huì)作出什么反應(yīng)?
  • 當(dāng)用戶插拔耳機(jī)時(shí), App 中的聲音功能會(huì)作出什么反應(yīng)?
    音頻會(huì)話的配置會(huì)影響 App 運(yùn)行期間幾乎所有的音頻活動(dòng)(除了通過系統(tǒng)聲音服務(wù) API 播放的 UI 音效)。開發(fā)者可以通過查詢音頻會(huì)話來獲取 App 運(yùn)行設(shè)備上的硬件特性(頻道數(shù)、采樣率等)。這些硬件特性因設(shè)備而異, App 可以根據(jù)用戶行為改變這些特性。
    開發(fā)者可以顯式得開啟或關(guān)閉自己的音頻會(huì)話。開發(fā)者需要在 App 開始播放聲音或使用錄音功能之前開啟音頻會(huì)話。另外,系統(tǒng)可以在接到電話或鬧鐘響起時(shí)關(guān)閉App音頻會(huì)話,這種行為被稱為中斷(interruption)。音頻會(huì)話的 API 中提供了對(duì)中斷進(jìn)行響應(yīng)和恢復(fù)的方法。

音頻會(huì)話的默認(rèn)行為

音頻會(huì)話具有如下的默認(rèn)行為:

  • 支持后臺(tái)播放,不支持錄音
  • 當(dāng)用戶將手機(jī)切換到靜音模式后,App 會(huì)被靜音。
  • 設(shè)備鎖屏后,App 會(huì)被靜音。
  • 當(dāng) App 的音頻開始后,設(shè)備正在播放的其他聲音會(huì)被靜音。

上述行為由默認(rèn)音頻會(huì)話類別 <code>AVAudioSessionCategorySoloAmbient</code> 提供。音頻會(huì)話類別(coming soon)介紹了如何在 App 內(nèi)使用類別。
盡管音頻會(huì)話會(huì)在 App 開始播放或錄制音頻時(shí)自動(dòng)開啟,但這種默認(rèn)的開啟方式會(huì)帶來風(fēng)險(xiǎn)。舉例來說,如果用戶使用 App 過程中有電話打入,而用戶選擇了拒接電話讓 App 繼續(xù)運(yùn)行。如果沒有使用合理的后臺(tái)播放技術(shù),那 App 的聲音將不會(huì)再播放。下一章(coming soon)描述了一些處理這類問題的策略,處理中斷(coming soon)中有進(jìn)一步的討論。

開發(fā)者可以在開發(fā)過程中使用這種默認(rèn)行為來提高開發(fā)效率。如果要發(fā)布 App ,那么只有在以下場(chǎng)景中才能安全的忽略音頻會(huì)話:

  • App 除了系統(tǒng)聲音服務(wù)(<code>System Sound Services</code>)或 <code>UIKit</code> 中的 <code>playInputClick</code> 方法外,不使用其他音頻 API 處理音頻。
    系統(tǒng)聲音服務(wù)是一種用來播放UI音效及觸發(fā)震動(dòng)的IOS技術(shù),不適用于其他任何場(chǎng)景。詳情見System Sound Services Reference
    UIKit 中的 <code>playInputClick</code> 方法允許開發(fā)者在特定的輸入或鍵盤輔助視圖(accessory view)中播放標(biāo)準(zhǔn)的鍵盤按鍵音。它的音頻會(huì)話行為由系統(tǒng)自動(dòng)處理。詳情見Playing Input Clicks
  • App 不使用音頻

如果不滿足上述條件,一定不要在需要發(fā)布的 App 中使用默認(rèn)的音頻會(huì)話。

為什么通常情況下默認(rèn)的音頻會(huì)話不能滿足開發(fā)者的要求

如果開發(fā)者不對(duì)音頻會(huì)話進(jìn)行初始化、配置和顯式調(diào)用,那么 App 就不能對(duì)中斷或音頻源的變化作出響應(yīng),也不能控制系統(tǒng)如何處理不同 App 間音頻的混合。
以下場(chǎng)景描述了音頻會(huì)話的默認(rèn)行為,以及開發(fā)者如何來改變它:

  1. 開發(fā)者開發(fā)了一款播放有聲書的 App。用戶開始聽《 The Merchant of Venice》,正當(dāng) Bassanio 大人要出場(chǎng)的時(shí)候,自動(dòng)鎖屏的時(shí)間到了,屏幕變黑了,有聲書的音頻也被靜音了。
    為了避免鎖屏靜音這種情況,開發(fā)者需為音頻會(huì)話配置一個(gè)支持后臺(tái)播放的類別,同時(shí)要在 <code>UIBackgoundModes</code> 中添加 <code>audio</code> 標(biāo)志。
  2. 開發(fā)者開發(fā)了一款使用基于 OpenAL 音效的第一視角射擊類游戲。游戲中提供背景音樂,但也為用戶提供了關(guān)閉游戲背景音樂,并播發(fā)音樂庫(kù)中的音樂的功能。在選擇一曲激昂的音樂開始播放后,用戶朝著敵軍開了一槍,槍響了,用戶播放的音樂卻停了。
    為了保證用戶選擇的音樂能不被干擾的繼續(xù)播放,需要將音頻會(huì)話設(shè)置為允許混合的模式。開發(fā)者可以選擇 <code>AVAudioSessionCategoryAmbient</code>類別 ,也可以通過修改 <code>AVAudioSessionCategoryPlayback</code> 類別來支持混合。
  3. 開發(fā)者開發(fā)了一款使用音頻隊(duì)列服務(wù)(<code>Audio Queue Services</code>)進(jìn)行后臺(tái)播放的流媒體電臺(tái) App。正當(dāng)用戶在收聽的時(shí)候,電話來了,App 的聲音按照期望中的那樣停止了。用戶選擇了拒接這個(gè)電話,關(guān)閉了鬧鐘,然后點(diǎn)擊播放按鈕來繼續(xù)收聽,卻發(fā)現(xiàn)未能如愿。用戶必須重啟 App 才能恢復(fù)后臺(tái)播放。
    要優(yōu)雅的處理這種音頻隊(duì)列的中斷,開發(fā)者需要設(shè)置合適的類別,注冊(cè) <code>AVAudioSessionInterruptionNotification</code> 通知,并讓 App 對(duì)不同的通知作出相應(yīng)的反應(yīng)。

系統(tǒng)怎樣解決音頻需求之間的競(jìng)爭(zhēng)

在 App 啟動(dòng)時(shí),系統(tǒng)的內(nèi)置 App(短信、音樂、Safari、電話等)可能會(huì)在后臺(tái)運(yùn)行。這些內(nèi)置的 App 可能會(huì)播放聲音,比如收到短信后。
如果將 IOS 設(shè)備看作一個(gè)飛機(jī)場(chǎng),把 App 看作滑行的飛機(jī),那么系統(tǒng)就是調(diào)度中心。飛機(jī)向調(diào)度中心發(fā)布一個(gè)使用聲音的請(qǐng)求,同時(shí)聲明它需要的優(yōu)先級(jí),而最終何時(shí)獲得超過“正在跑道上”使用音頻的其他飛機(jī)的權(quán)限由調(diào)度中心決定。App 通過音頻會(huì)話來跟系統(tǒng)進(jìn)行交互。下圖描述了一個(gè)典型的場(chǎng)景:你的 App 想要在音樂 App 正在播放音樂的時(shí)候播放聲音。這種情況下,你的 App 會(huì)中斷音樂 App。


圖片來自官方文檔

<small>
第一步,App 請(qǐng)求開啟它的音頻會(huì)話。這種請(qǐng)求可能會(huì)在 App 加載過程中產(chǎn)生,也可能會(huì)在響應(yīng)用戶點(diǎn)擊某個(gè)播放按鈕的事件中產(chǎn)生。第二步,系統(tǒng)開始處理這次請(qǐng)求。圖中的 SpeakHere App 使用了需要其他音頻靜音的類別。
在第三和第四步中,系統(tǒng)關(guān)閉了音樂 App 的音頻會(huì)話,停止了音樂在后臺(tái)的播放。最終,系統(tǒng)開啟了 SpeakHere 的音頻會(huì)話,SpeakHere 可以開始播放聲音了。
系統(tǒng)對(duì)于是否開啟或關(guān)閉設(shè)備上音頻會(huì)話有最終的決定權(quán)。決策過程中,電話總是擁有最高的優(yōu)先權(quán),沒有 App 的音頻權(quán)限能夠超過電話。接到電話后,無(wú)論當(dāng)前正在執(zhí)行什么音頻動(dòng)作或是設(shè)置了哪種音頻類別,App 都會(huì)被中斷,用戶都會(huì)獲得“你接到了電話”的提醒。
</small>

集成 <code>AVCaptureSession</code>

<code>AV Foudation</code> 中的捕獲 API(<code>AVCaptureDevice</code>、<code>AVCaptureSession</code>)可以使開發(fā)者得到同步獲取來自相機(jī)或麥克風(fēng)的音頻或視頻輸入。在 IOS7 中,表示麥克風(fēng)輸入的 <code>AVCaptureDevice</code> 對(duì)象可以共享 App 的 <code>AVAudioSession</code>。默認(rèn)情況下,<code>AVCaptureSession</code> 會(huì)在使用麥克風(fēng)的時(shí)候會(huì)給 <code>AVAudioSession</code> 設(shè)置最適合錄音的配置。如果將 <code>automaticallyConfiguresApplicationAudioSession</code> 屬性設(shè)為 <code>NO</code>,這種默認(rèn)配置會(huì)被當(dāng)前開發(fā)者的AVAudioSession配置覆蓋,<code>AVCaptureDevice</code> 也會(huì)不加修改的采用開發(fā)者的配置。在 AVCaptureSession Class ReferenceMedia Capture 中可以獲得更多相關(guān)信息。

初始化音頻會(huì)話

系統(tǒng)在 App 的加載過程中提供了一個(gè)音頻會(huì)話的對(duì)象。在處理中斷之前,開發(fā)者必須初始化這個(gè)會(huì)話。
<code>AV Foundation</code> 框架會(huì)利用開發(fā)者獲取對(duì) <code>AVAudioSession</code> 對(duì)象的引用時(shí)觸發(fā)的隱式初始化,來管理中斷。

//隱式初始化音頻會(huì)話
AVAudioSession *session = [AVAudioSession sharedInstance];

<code>session</code> 變量代表了一個(gè)已經(jīng)被初始化且可以馬上使用的音頻會(huì)話。官方推薦在使用 <code>AVAudioSession</code> 類中的中斷通知,或 <code>AVAudioPlayer</code> 和 <code>AVAudioRecorder</code> 的代理協(xié)議來處理音頻中斷時(shí),隱式的初始化音頻會(huì)話。

添加音量和音頻源管理

<code>MPVolumeView</code> 類提供了在 App 中控制音量和音頻源的方法。音量視圖提供了一個(gè)控制音量的滑塊和一個(gè)選擇音頻輸出源的按鈕。官方建議在將音頻源切換到內(nèi)置揚(yáng)聲器時(shí),使用 <code>MPVolumeView</code> 的音頻源選擇器(route picker)而不是 <code>AVAudioSessionPortOverride</code>。詳情見 MPVolumeView Class Reference

響應(yīng)遙控器事件

用戶可以通過遙控器事件來控制 App 中的多媒體。開發(fā)者可能希望 App 中播放的音頻或視頻內(nèi)容對(duì)來自 transport controls 或外接輔助設(shè)備的遙控事件做出響應(yīng)。IOS 將這些命令轉(zhuǎn)化為 <code>UIEvent</code> 對(duì)象分發(fā)給 App。App 接收到事件后將它們發(fā)送給對(duì)應(yīng)的 first responder。如果 first responder 不對(duì)事件進(jìn)行處理,那么事件將會(huì)在 responder 鏈中向上傳遞。
只有正在播放音頻、且具有“Now Playing”信息的 app,才能對(duì)遙控器事件做出響應(yīng)。詳情見 Remote Control EventsMPNowPlayingInfoCenter Class Reference

開啟或關(guān)閉音頻會(huì)話

雖然系統(tǒng)在 App 加載的時(shí)候自動(dòng)開啟你的音頻會(huì)話,但蘋果官方推薦的做法是在 App 的 <code>viewDidLoad</code> 方法中顯式的開啟,并在開啟前設(shè)置合適的硬件參數(shù)。為 App 進(jìn)行硬件優(yōu)化 中有相關(guān)的示例代碼。通過這種方式,開發(fā)者可以測(cè)試音頻會(huì)話是否成功開啟。如果 App 中包含一個(gè)類似播放/暫停的 UI 元素,在用戶按下播放鍵時(shí)開啟會(huì)話則是更好的方式。在切換音頻會(huì)話的開啟/關(guān)閉狀態(tài)時(shí),對(duì)是否成功的切換了會(huì)話狀態(tài)做出檢查是有必要的。開發(fā)者應(yīng)在代碼中對(duì)系統(tǒng)駁回的請(qǐng)求進(jìn)行優(yōu)雅的處理。
系統(tǒng)會(huì)在鬧鐘提醒、日歷提醒或接到電話時(shí)將關(guān)閉你的音頻會(huì)話。當(dāng)用戶關(guān)閉提醒或拒接電話后,系統(tǒng)會(huì)允許你重新開啟會(huì)話。在中斷結(jié)束后是否重新開啟音頻會(huì)話由 App 的類型決定,[Audio Guidelines By App Type](Audio Guidelines By App Type.md) 中有相關(guān)的介紹。
下面的代碼展示了如何開啟音頻會(huì)話。

NSError *activationError = nil;
BOOL success = [[AVAudioSession sharedInstance] setActive: YES error: &activationError];
if (!success) { /* handle the error in activationError */ }

將 <code>setActive</code> 的參數(shù)設(shè)置為 <code>NO</code> 可以關(guān)閉會(huì)話。
如果使用 <code>AVAudioPlayer</code> 或 <code>AVAudioRecorder</code> 來播放或錄制音頻時(shí),系統(tǒng)會(huì)負(fù)責(zé)在中斷結(jié)束后重新開啟音頻會(huì)話。然而,官方推薦通過注冊(cè)消息通知來顯式開啟會(huì)話,來保證會(huì)話成功開啟并對(duì) App 的狀態(tài)和 UI 進(jìn)行更新。
大多數(shù) App 不需要顯式的關(guān)閉音頻會(huì)話。一些需要顯式關(guān)閉的特例包括 VoIP(網(wǎng)絡(luò)電話)App、逐向(在轉(zhuǎn)彎時(shí)對(duì)用戶做出提醒)導(dǎo)航 App 和某些錄音 App。
對(duì)于一般在后臺(tái)運(yùn)行網(wǎng)絡(luò)電話 App,要保證它的音頻會(huì)話在處理通話時(shí)是開啟的,而在后臺(tái)準(zhǔn)備接收通話時(shí)則處于關(guān)閉狀態(tài)。
對(duì)于使用錄音類別的 App 的音頻會(huì)話僅在錄音時(shí)開啟。在錄音開始前和錄音結(jié)束后要關(guān)閉會(huì)話以保證類似短信提示音的其他聲音能夠順利播放。

App加載時(shí)檢查是否存在正在播放的其他音頻

在用戶打開 App 時(shí),設(shè)備可能正在播放其他的聲音:音樂 App 可能正在播放音樂,或者瀏覽器正在播放流媒體。這種情況產(chǎn)生的影響對(duì)于游戲 App 來說可能更為顯著。許多游戲會(huì)有自己的背景音樂和音效。IOS Human Interface Guidelines 建議開發(fā)者假定用戶在玩游戲時(shí)希望保持他們?cè)瓉聿シ诺囊纛l作為背景音樂,同時(shí)保留游戲的音效。
檢查 <code>otherAudioPlaying</code> 的屬性值來判斷 App 加載過程中是否正在播放其他音頻;如果是的話,將游戲的背景音樂靜音,并使用 <code>AVAudioSessionCategorySoloAmbient</code> 類別。詳情見音頻會(huì)話類別(coming soon)。

跨 App 音頻(Inter-App Audio)

跨 App 音頻的最基礎(chǔ)的使用形式是通過一個(gè)節(jié)點(diǎn)(node) app 將它的音頻輸出到另一個(gè)寄主(host) App。寄主 App 可能會(huì)將它的輸出發(fā)送給節(jié)點(diǎn) App,經(jīng)過節(jié)點(diǎn) App 的處理后,將處理結(jié)果反饋給寄主 App。寄主 App 需要一個(gè)始終處于開啟狀態(tài)的音頻會(huì)話,而節(jié)點(diǎn) App 只需要在從寄主 App 或系統(tǒng)接收音頻輸入時(shí)開啟音頻會(huì)話。根據(jù)以下方案來設(shè)置跨 App 的音頻:

  • 為寄主 App 和節(jié)點(diǎn) App 設(shè)置“inter-app-audio”權(quán)限
  • 為寄主 App 在 <code>UIBackgoundModes</code> 添加 <code>audio</code> 屬性。
  • 為使用音頻輸入輸出源、同時(shí)連接到跨 App 音頻寄主的節(jié)點(diǎn) app 的 <code>UIBackgoundModes</code> 添加 <code>audio</code> 屬性。
  • 將寄主和節(jié)點(diǎn) App 的類別設(shè)為 <code> AVAudioSessionCategoryOptionMixWithOthers</code>。
  • 對(duì)于連接到寄主的節(jié)點(diǎn) App,保證它的音頻會(huì)話在收到系統(tǒng)的音頻輸入或產(chǎn)生音頻輸出時(shí)處于開啟狀態(tài)。

以上內(nèi)容翻譯自蘋果官方文檔,僅供學(xué)習(xí),請(qǐng)勿用于商業(yè)用途,侵刪。轉(zhuǎn)載注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,055評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,346評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,889評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,118評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,637評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,558評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,739評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,980評(píng)論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評(píng)論 1 280
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,347評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,702評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容