分享音訊輸入內容

音訊輸入通常來自內建麥克風、外部麥克風或裝置連接的音訊介面。音訊輸入內容也可以來自手機對話。

有時候,兩個以上的應用程式可能會想「擷取」相同的音訊輸入內容。這些模組可能執行了不同的工作。舉例來說,某些接收音訊的應用程式可能是「錄音」,就像簡單的語音錄音工具,其他應用程式也可能是「聽取語音」,例如 Google 助理或回應語音指令的無障礙服務。

無論是哪種情況,這些應用程式都可以接收音訊輸入內容。 在這個頁面中,無論應用程式是在錄音還是只是聆聽,我們都會使用「擷取」一詞。

如果兩個以上的應用程式想要同時擷取音訊,則可能會發生問題,將相同來源的音訊訊號傳送給所有這些應用程式。本頁面說明 Android 系統如何在多個擷取音訊的應用程式之間分享音訊輸入。

Android 10 之前的行為

在 Android 10 之前,一次只能擷取一個應用程式擷取輸入音訊串流。如果某些應用程式已在錄製或聆聽音訊,應用程式可以建立 AudioRecord 物件,但系統會在您呼叫 AudioRecord.startRecording() 時傳回錯誤,且不會開始記錄。

有一個例外情況是,具有特殊權限的應用程式 (例如 Google 助理或無障礙服務) 具備 android.permission.CAPTURE_AUDIO_HOTWORD 權限,並使用 HOTWORD 類型的音訊來源。在此情況下,其他應用程式可能會開始錄影。發生上述情況時,具有特殊權限的應用程式終止了,新的應用程式擷取輸入內容。

Android 9 新增了一項變更:只有在前景執行的應用程式 (或前景服務) 才能擷取音訊輸入內容。當沒有前景服務或前景 UI 元件的應用程式開始擷取時,應用程式會繼續執行,但即使是唯一擷取音訊的應用程式,仍會保持靜音。

Android 10 行為

在 Android 10 之前的行為為「先進先進」。 應用程式開始擷取音訊後,在擷取音訊的應用程式前,任何其他應用程式都無法存取音訊輸入。

Android 10 設有優先順序機制,可在應用程式執行期間,在應用程式之間切換輸入音訊串流。在大多數情況下,如果新應用程式取得音訊輸入,先前擷取的應用程式仍會繼續執行,但會無聲。在某些情況下,系統可能會繼續將音訊提供給兩個應用程式。以下說明各種共用情況

這個配置類似於處理多個使用音訊輸出的應用程式。不過,音訊焦點由透過程式取得及釋放焦點的程式要求管理,而此處描述的輸入切換配置是以優先順序政策為基礎,在新應用程式開始擷取音訊時自動套用。

為了擷取音訊,Android 會區分兩種應用程式:

  • 「一般」應用程式是由使用者安裝。
  • 裝置會預先安裝「特殊權限」的應用程式。包括 Google 助理和所有無障礙服務。

此外,如果應用程式使用「會影響隱私權」的音訊來源,則會以不同方式處理:CAMCORDERVOICE_COMMUNICATION

使用及分享音訊輸入的優先順序規則如下:

  • 具備特殊權限的應用程式優先順序高於一般應用程式。
  • 具有可見前景 UI 的應用程式優先順序高於背景應用程式。
  • 如果應用程式是從敏感來源擷取音訊,則相較於未使用應用程式,應用程式的優先順序更高。
  • 兩個一般應用程式無法同時擷取音訊。
  • 在某些情況下,具有特殊權限的應用程式可能會將音訊輸入提供給其他應用程式。
  • 如果有兩個相同優先順序的背景應用程式正在擷取音訊,最後一個啟動應用程式的優先程度會較高。

共用情境

當兩個應用程式嘗試擷取音訊時,兩個應用程式都可能接收輸入信號,或者其中一個應用程式可以接收靜音。

這四種主要情境如下:

  • Google 助理 + 一般應用程式
  • 無障礙服務 + 一般應用程式
  • 兩種普通應用程式
  • 語音通話 + 一般應用程式

Google 助理 + 一般應用程式

Google 助理已預先安裝,且具備 RoleManager.ROLE_ASSISTANT 角色,因此是具有特殊權限的應用程式。其他具有這個角色的預先安裝應用程式同樣受到類似處理。

Android 會根據下列規則分享輸入音訊:

  • 無論在前景或背景運作,Google 助理都可接收音訊,除非有另一個應用程式正在擷取音訊內容。

  • 除非 Google 助理在螢幕頂端有可見的 UI 元件,否則應用程式會接收音訊。

請注意,只有在 Google 助理於背景執行時,其他應用程式才能接收音訊。

無障礙服務 + 一般應用程式

AccessibilityService 需要嚴格的宣告

Android 會根據下列規則分享輸入音訊:

  • 如果服務的 UI 顯示在頂端,則服務和應用程式都會接收音訊輸入。此行為提供使用語音指令控制語音通話或影片拍攝等功能。

  • 如果服務並非位於上層,就會像下方的一般雙應用程式情況一樣處理。

兩種普通應用程式

當兩個應用程式同時擷取音訊時,只有一個應用程式可以接收音訊,另一個應用程式會無聲。

Android 會根據下列規則分享輸入音訊:

  • 如果兩個應用程式都不對隱私有所敏感,則具有 UI 的應用程式可以接收音訊。如果兩個應用程式都沒有 UI,則最先開始擷取音訊的應用程式才會收到音訊。
  • 如果其中一個應用程式有隱私機密性,即使該應用程式在頂端有 UI 或最近才開始擷取,該應用程式仍會收到音訊,而另一個應用程式會開始靜音。
  • 如果兩個應用程式都具備隱私敏感性,則啟動最近期擷取音訊的應用程式就會停止接收音訊,而另一個應用程式則不會設為靜音。

語音通話 + 一般應用程式

如果 AudioManager.getMode() 傳回的音訊模式為 MODE_IN_CALLMODE_IN_COMMUNICATION,則已啟用語音通話。

Android 會根據下列規則分享輸入音訊:

Android 11 行為

Android 11 (API 級別 30) 遵循上述 Android 10 優先順序配置。此外,無論所選用途為何,這個做法在 AudioRecordMediaRecorderAAudioStream 中也提供新的方法,讓您啟用及停用並行擷取音訊的功能。

新方法包括:

setPrivacySensitive()true 時,擷取用途為不公開,即使有特殊權限的 Google 助理無法並行擷取。這項設定會覆寫依附音訊來源的預設行為。舉例來說,VOICE_COMMUNICATION 預設為不公開,但 UNPROCESSED 不會。

設定變更

當多個應用程式同時擷取音訊時,只有一或兩個應用程式會「啟用」(接收音訊),而其他應用程式則會設為靜音 (接收靜音)。當使用中的應用程式有所變更,音訊架構可能會根據下列規則重新設定音訊路徑:

  • 每個使用中應用程式的音訊輸入裝置可能會改變,例如從內建麥克風連接至連接的藍牙耳機。
  • 與優先順序最高的應用程式相關聯的預先處理作業已啟用。其他預先處理作業都會遭到忽略。

由於優先順序較高的應用程式可能會處於靜音狀態,因此您可以在 AudioRecordMediaRecorder 物件上註冊 AudioManager.AudioRecordingCallback,以便在設定變更時收到通知。可能的變更如下:

  • 影片處於靜音或無聲模式
  • 已變更裝置
  • 預先處理已變更
  • 串流屬性已變更 (取樣率、頻道遮罩、取樣格式)

您必須先呼叫 AudioRecord.registerAudioRecordingCallback(),才能開始擷取。只有在應用程式接收音訊且發生變更時,才會執行回呼。

onRecordingConfigChanged() 方法會傳回包含目前音訊擷取狀態的 AudioRecordingConfiguration。請使用以下方法瞭解變更:

isClientSilenced()
如果根據擷取政策的規定,目前傳回用戶端的音訊遭到靜音,則傳回 true。
getAudioDevice()
傳回使用中的音訊裝置。
getEffects()
傳回使用中的預先處理效果。請注意,如果用戶端並非優先順序最高的使用中應用程式,則有效效果可能不會與 getClientEffects() 傳回的效果相同。
getFormat()
傳回串流屬性。請注意,用戶端收到的實際音訊資料一律會採用 getClientFormat() 傳回的必要格式。這個架構會自動執行必要的重新取樣、管道和格式,從硬體介面使用的格式,轉換為用戶端指定的格式。
AudioRecord.getActiveRecordingConfiguration()
傳回使用中的錄製設定。

您可以呼叫 AudioManager.getActiveRecordingConfigurations(),取得裝置上所有進行中的錄製內容的一般檢視畫面。