溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Android音頻焦點(diǎn)管理實(shí)例分析

發(fā)布時(shí)間:2022-01-27 09:10:22 來(lái)源:億速云 閱讀:141 作者:kk 欄目:開(kāi)發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)Android音頻焦點(diǎn)管理實(shí)例分析,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

    音頻焦點(diǎn)管理的意義

    兩個(gè)或兩個(gè)以上的 Android 應(yīng)用可同時(shí)向同一輸出流播放音頻。系統(tǒng)會(huì)將所有音頻流混合在一起。雖然這是一項(xiàng)出色的技術(shù),但卻會(huì)給用戶帶來(lái)很大的困擾。為了避免所有音樂(lè)應(yīng)用同時(shí)播放,Android 引入了“音頻焦點(diǎn)”的概念。 一次只能有一個(gè)應(yīng)用獲得音頻焦點(diǎn)。

    當(dāng)您的應(yīng)用需要輸出音頻時(shí),它需要請(qǐng)求獲得音頻焦點(diǎn),獲得焦點(diǎn)后,就可以播放聲音了。不過(guò),在您獲得音頻焦點(diǎn)后,您可能無(wú)法將其一直持有到播放完成。其他應(yīng)用可以請(qǐng)求焦點(diǎn),從而占有您持有的音頻焦點(diǎn)。如果發(fā)生這種情況,您的應(yīng)用應(yīng)暫停播放或降低音量,以便于用戶聽(tīng)到新的音頻源。

    音頻焦點(diǎn)管理的行為準(zhǔn)則

    • 在即將開(kāi)始播放之前調(diào)用 requestAudioFocus(),并驗(yàn)證調(diào)用是否返回 AUDIOFOCUS_REQUEST_GRANTED。

    • 在其他應(yīng)用獲得音頻焦點(diǎn)時(shí),應(yīng)該停止或者暫停播放,或者降低音量。

    • 播放停止后應(yīng)該放棄音頻焦點(diǎn)

    版本兼容

    從Android 8.0(O版本,API 26)開(kāi)始,音頻焦點(diǎn)的請(qǐng)求方式以及系統(tǒng)管理有了細(xì)微的變化,下面分兩部分來(lái)說(shuō)明。

    在Android 8.0(API 26) 之前對(duì)音頻焦點(diǎn)具體處理實(shí)現(xiàn)

    當(dāng)想錄音或者播放歌曲的時(shí)候,最好(非必須)先請(qǐng)求音頻焦點(diǎn),這個(gè)時(shí)候需要調(diào)用AudioManager.requestAudioFocus()方法,函數(shù)原型如下

    AudioManager.requestAudioFocus(OnAudioFocusChangeListener l, int streamType, int durationHint)

    第一個(gè)參數(shù)用于監(jiān)聽(tīng)焦點(diǎn)變化

    第二個(gè)參數(shù)表明請(qǐng)求的音頻焦點(diǎn)影響的是那種類(lèi)型流,例如,如果我們錄音,我們肯定是要影響Music這一類(lèi)型的音頻流,因此可以選擇AudioManager.STREAM_MUSIC。當(dāng)然還有許多類(lèi)型。

    /** 通話相關(guān) */
    public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
    /** 系統(tǒng)聲音 */
    public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
    /** 鈴聲 */
    public static final int STREAM_RING = AudioSystem.STREAM_RING;
    /** 音樂(lè)相關(guān) */
    public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
    /** 鬧鐘相關(guān) */
    public static final int STREAM_ALARM = AudioSystem.STREAM_ALARM;

    第三個(gè)參數(shù)用于表明音頻焦點(diǎn)的持續(xù)時(shí)間,這個(gè)很關(guān)鍵,它也有許多種類(lèi)型,下面一一列出。

    • AudioManager.AUDIOFOCUS_GAIN: API文檔說(shuō)請(qǐng)求的這類(lèi)音頻焦點(diǎn)持續(xù)時(shí)間是未知的,通常用來(lái)表示長(zhǎng)時(shí)間獲取焦點(diǎn),可以用來(lái)播放音樂(lè),錄音等等。

    • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: 表明請(qǐng)求的音頻焦點(diǎn)持續(xù)時(shí)間比較短,通常用來(lái)播放導(dǎo)航路線的聲音,或者播放通知聲音。

    • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: 這個(gè)也是表明請(qǐng)求的音頻焦點(diǎn)持續(xù)時(shí)間比較短,但是在這段時(shí)間內(nèi),它希望其他應(yīng)用以較低音量繼續(xù)播放。例如,我們?cè)谑褂脤?dǎo)航的時(shí)候可以聽(tīng)音樂(lè),當(dāng)出現(xiàn)導(dǎo)航語(yǔ)音的時(shí)候,音樂(lè)音量會(huì)降低以便我們能聽(tīng)清楚導(dǎo)航的語(yǔ)音,當(dāng)導(dǎo)航語(yǔ)音播放完畢后,音樂(lè)恢復(fù)音量,繼續(xù)播放。

    • AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE: 這個(gè)也是表明音請(qǐng)求的音頻焦點(diǎn)持續(xù)時(shí)間比較短,但是在這段時(shí)間內(nèi),不希望任何應(yīng)用(包括系統(tǒng)應(yīng)用)來(lái)做任何與音頻相關(guān)的事情,就算是降低音量播放音樂(lè)也是不被希望的。例如當(dāng)我們進(jìn)行錄音或者語(yǔ)音識(shí)別的時(shí)候,我們不希望其他的聲音出現(xiàn)干擾。

    AudioManager.requestAudioFocus()的返回值表明請(qǐng)求的結(jié)果AudioManager.AUDIOFOCUS_REQUEST_FAILED表明請(qǐng)求焦點(diǎn)失敗,AudioManager.AUDIOFOCUS_REQUEST_GRANTED表明請(qǐng)求焦點(diǎn)成功。

    當(dāng)我們成功請(qǐng)求焦點(diǎn)后,就可以做一些與音頻有關(guān)的事情,例如播放音樂(lè),錄音,或者語(yǔ)音識(shí)別。當(dāng)完成這些工作后,我們必須調(diào)用AudioManager.abandonAudioFocus(onAudioFocusChangeListener l)釋放音頻焦點(diǎn)。

    8.0 之后實(shí)現(xiàn)

    從Android 8.0開(kāi)始(API 26),請(qǐng)求音頻焦點(diǎn)的方式以及系統(tǒng)對(duì)音頻焦點(diǎn)變化的管理有些微妙的變化。 首先,對(duì)音頻焦點(diǎn)變化的管理的變化體現(xiàn)在兩個(gè)方面,延遲獲取焦點(diǎn)和自動(dòng)降低音量。

    延遲獲取焦點(diǎn)

    在Android 8.0之前,當(dāng)我們請(qǐng)求音頻焦點(diǎn)的時(shí)候,只會(huì)返回兩種結(jié)果,要么請(qǐng)求成功(AUDIOFOCUS_REQUEST_GRANTED),要么請(qǐng)求失敗(AUDIOFOCUS_REQUEST_FAILED)。

    而從Android 8.0開(kāi)始,還有一種結(jié)果,延遲成功請(qǐng)求(AUDIOFOCUS_REQUEST_DELAYED),這個(gè)也是成功的請(qǐng)求,但是這個(gè)請(qǐng)求具有延遲性。例如當(dāng)我們處于通話狀態(tài)的時(shí)候,我們很顯然不希望任何app來(lái)獲取到音頻焦點(diǎn)來(lái)做些事,例如播放音樂(lè)。

    然而只有設(shè)置過(guò)AudioFocusRequest.Builder.setAcceptsDelayedFocusGain(true)才能獲取到這種結(jié)果,這個(gè)我們后面會(huì)講到。那么我們?cè)趺粗朗裁磿r(shí)候獲取到了音頻焦點(diǎn)呢,當(dāng)然還需要設(shè)置AudioManager.OnAudioFocusChangeListener這個(gè)音頻焦點(diǎn)變化的監(jiān)聽(tīng)器,通過(guò)回調(diào)確認(rèn)何時(shí)獲取到了音頻焦點(diǎn)。

    自動(dòng)降低音量

    在Android 8.0之前,如果請(qǐng)求焦點(diǎn)使用了AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK參數(shù),它表明希望擁有了音頻焦點(diǎn)的其他應(yīng)用降低音量來(lái)使用音頻,然而并不是所有的應(yīng)用都會(huì)這樣做(有可能開(kāi)發(fā)者忘記了優(yōu)化),因?yàn)檫@并不是系統(tǒng)強(qiáng)制的。But, 從Android 8.0開(kāi)始,這個(gè)降低音量的工作,就是系統(tǒng)默認(rèn)行為了,可以說(shuō)是一個(gè)良心的優(yōu)化。

    如果我不希望系統(tǒng)自動(dòng)給我降低音量,而是想自己暫停音頻相關(guān)的工作,那咋辦?這個(gè)可以通過(guò)AudioFocusRequest.Builder.setWillPauseWhenDucked(true)方法取消系統(tǒng)的默認(rèn)行為,然后通過(guò)監(jiān)聽(tīng)音頻焦點(diǎn)變化

    音頻焦點(diǎn)請(qǐng)求方式

    從 Android 8.0(API 級(jí)別 26)開(kāi)始,當(dāng)您調(diào)用 requestAudioFocus() 時(shí),必須提供 AudioFocusRequest 參數(shù)。要釋放音頻焦點(diǎn),請(qǐng)調(diào)用 abandonAudioFocusRequest() 方法,該方法也接受 AudioFocusRequest 作為參數(shù)。在請(qǐng)求和放棄焦點(diǎn)時(shí),應(yīng)使用相同的 AudioFocusRequest 實(shí)例

    要?jiǎng)?chuàng)建 AudioFocusRequest,請(qǐng)使用 AudioFocusRequest.Builder。由于焦點(diǎn)請(qǐng)求始終必須指定請(qǐng)求的類(lèi)型,因此此類(lèi)型會(huì)包含在構(gòu)建器的構(gòu)造函數(shù)中。使用構(gòu)建器的方法來(lái)設(shè)置請(qǐng)求的其他字段

    • setFocusGain(): 只有這個(gè)方法是必須的,而傳入的參數(shù)與8.0之前使用AudioManager.requestAudioFocus()傳入的第三個(gè)參數(shù)一樣,都是用來(lái)表示持續(xù)時(shí)間。

    • setAudioAttributes(): 這個(gè)方法是用來(lái)描述app的使用情況。這方法需要傳入一個(gè)AudioAttributes對(duì)象,這個(gè)對(duì)象也是使用Builder模式來(lái)構(gòu)造,例如使用AudioAttributes.Builder.setUsage()來(lái)描述使用這個(gè)音頻來(lái)干什么,我們可以傳入一個(gè)AudioAttributes.USAGE_MEDIA來(lái)表明用這個(gè)音頻來(lái)作為媒體文件來(lái)播放,也可以傳入一個(gè)AudioAttributes.USAGE_ALARM來(lái)表明用這個(gè)來(lái)作為鬧鈴。

    • setWillPauseWhenDucked(): 這個(gè)前面說(shuō)過(guò),是為了覆蓋系統(tǒng)默認(rèn)降低音量的行為,但是必須要設(shè)置AudioManager.OnAudioFocusChangeListener才能自己處理這類(lèi)情況。

    • setAcceptsDelayedFocusGain(): 這個(gè)前面也說(shuō)過(guò),這個(gè)是為了能夠延遲獲取到焦點(diǎn)的必須條件,但是同時(shí)也必須要設(shè)置AudioManager.OnAudioFocusChangeListener才能得知何時(shí)獲取到焦點(diǎn)。

    • setOnAudioFocusChangeListener(): 音頻焦點(diǎn)變化監(jiān)聽(tīng)器。值得一提的是這個(gè)方法有個(gè)重載的方法,有一個(gè)重載方法有兩個(gè)參數(shù),第二個(gè)參數(shù)為Handler對(duì)象,看到Handler應(yīng)該明白了,是為了使用它的消息隊(duì)列來(lái)順序處理這個(gè)回調(diào)

    響應(yīng)音頻焦點(diǎn)更改

    當(dāng)應(yīng)用獲得音頻焦點(diǎn)后,它必須能夠在其他應(yīng)用為自己請(qǐng)求音頻焦點(diǎn)時(shí)釋放該焦點(diǎn)。出現(xiàn)這種情況時(shí),您的應(yīng)用會(huì)收到對(duì) AudioFocusChangeListener 中的 onAudioFocusChange() 方法的調(diào)用,該方法是您在應(yīng)用調(diào)用 requestAudioFocus() 時(shí)指定的。

    傳遞給 onAudioFocusChange() 的 focusChange 參數(shù)表示所發(fā)生的更改類(lèi)型。它對(duì)應(yīng)于獲取焦點(diǎn)的應(yīng)用所使用的持續(xù)時(shí)間提示。您的應(yīng)用應(yīng)該做出適當(dāng)?shù)捻憫?yīng)

    暫時(shí)性失去焦點(diǎn)

    如果焦點(diǎn)更改是暫時(shí)性的(AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK 或 AUDIOFOCUS_LOSS_TRANSIENT),您的應(yīng)用應(yīng)該降低音量(如果您不依賴(lài)于自動(dòng)降低音量)或暫停播放,否則保持相同的狀態(tài)。

    在暫時(shí)性失去音頻焦點(diǎn)時(shí),您應(yīng)該繼續(xù)監(jiān)控音頻焦點(diǎn)的變化,并準(zhǔn)備好在重新獲得焦點(diǎn)后恢復(fù)正常播放。當(dāng)搶占焦點(diǎn)的應(yīng)用放棄焦點(diǎn)時(shí),您會(huì)收到一個(gè)回調(diào) (AUDIOFOCUS_GAIN)。此時(shí),您可以將音量恢復(fù)到正常水平或重新開(kāi)始播放。

    永久性失去焦點(diǎn)

    如果是永久性失去音頻焦點(diǎn) (AUDIOFOCUS_LOSS),則其他應(yīng)用會(huì)播放音頻。您的應(yīng)用應(yīng)立即暫停播放,因?yàn)樗粫?huì)收到 AUDIOFOCUS_GAIN 回調(diào)。要重新開(kāi)始播放,用戶必須執(zhí)行明確的操作,例如在通知或應(yīng)用界面中按播放傳輸控件。

    附音頻基礎(chǔ)知識(shí)

    采樣和采樣頻率:一秒鐘內(nèi)采樣的次數(shù)稱(chēng)為采樣頻率。采樣頻率越高,越接近原始信號(hào),但是也加大了運(yùn)算處理的復(fù)雜度。根據(jù)Nyquist采樣定理,要想重建原始信號(hào),采樣頻率必須大于信號(hào)中最高頻率的兩倍。人能感受到的頻率范圍為20HZ--20kHZ, 一般音樂(lè)的采樣頻率為44.1kHZ, 更高的可以是48kHZ和96kHZ,不過(guò)一般人用耳聽(tīng)感覺(jué)不出差別了。語(yǔ)音主要是以溝通為主,不需要像音樂(lè)那樣清晰,用16k采樣的語(yǔ)音就稱(chēng)為高清語(yǔ)音了。現(xiàn)在主流的語(yǔ)音采樣頻率為16kHz。

    采樣位數(shù):數(shù)字信號(hào)是用0和1來(lái)表示的。采樣位數(shù)就是采樣值用多少位0和1來(lái)表示,也叫采樣精度,用的位數(shù)越多就越接近真實(shí)聲音。如用8位表示,采樣值取值范圍就是-128--127,如用16位表示,采樣值取值范圍就是-32768--32767?,F(xiàn)在一般都用16位采樣位數(shù)。

    聲道:聲道是指處理的聲音是單聲道還是立體聲。Android支持雙聲道立體聲和單聲道。CHANNEL_IN_MONO單聲道,CHANNEL_IN_STEREO立體聲。單聲道在聲音處理過(guò)程中只有單數(shù)據(jù)流,而立體聲則需要左、右聲道的兩個(gè)數(shù)據(jù)流。顯然,立體聲的效果要好,但相應(yīng)的數(shù)據(jù)量要比單聲道的數(shù)據(jù)量加倍。

    碼率:就是比特率。比特率是指每秒傳送的比特(bit)數(shù)。碼率=采樣率X采樣位數(shù)X聲道數(shù)。

    音頻采集和播放:一般用專(zhuān)門(mén)的芯片(通常叫codec芯片)采集音頻,做AD轉(zhuǎn)換,然后把數(shù)字信號(hào)通過(guò)I2S總線(主流用I2S總線,也可以用其他總線,比如PCM總線)送給CPU處理(也有的會(huì)把codec芯片與CPU芯片集成在一塊芯片中)。當(dāng)要播放時(shí)CPU會(huì)把音頻數(shù)字信號(hào)通過(guò)I2S總線送給codec芯片,然后做DA轉(zhuǎn)換得到模擬信號(hào)再播放出來(lái)。

    Android是什么

    Android是一種基于Linux內(nèi)核的自由及開(kāi)放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國(guó)Google公司和開(kāi)放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開(kāi)發(fā)。

    上述就是小編為大家分享的Android音頻焦點(diǎn)管理實(shí)例分析了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI