Dane wejściowe audio pochodzą zwykle z wbudowanego mikrofonu, mikrofonu zewnętrznego lub interfejsu audio podłączonego do urządzenia. Dane wejściowe audio mogą też pochodzić z rozmowy telefonicznej.
Czasami 2 lub więcej aplikacji może chcieć „przechwycić” te same dane wejściowe audio. Mogą one wykonywać różne zadania. Na przykład niektóre aplikacje, które odbierają dźwięk, mogą „nagrywać”, np. prosty dyktafon, a inne mogą „nasłuchiwać”, np. Asystent Google lub usługa ułatwień dostępu, która reaguje na polecenia głosowe.
W obu przypadkach te aplikacje chcą otrzymywać dane wejściowe audio. Na tej stronie używamy terminu „przechwytywanie” niezależnie od tego, czy aplikacja nagrywa, czy tylko nasłuchuje.
Jeśli 2 lub więcej aplikacji chce przechwytywać dźwięk w tym samym czasie, może wystąpić problem z dostarczeniem sygnału audio z tego samego źródła do wszystkich tych aplikacji. Na tej stronie opisujemy, jak system Android udostępnia dane wejściowe audio między wieloma aplikacjami, które przechwytują dźwięk.
Działanie przed Androidem 10
Przed Androidem 10 wejściowy strumień audio mógł być przechwytywany tylko przez 1 aplikację naraz. Jeśli jakaś aplikacja już nagrywała lub nasłuchiwała dźwięk, Twoja
aplikacja mogła utworzyć obiekt AudioRecord, ale po wywołaniu AudioRecord.startRecording()
zwracany był błąd i nagrywanie się nie rozpoczynało.
Wyjątkiem od tej reguły było, gdy uprzywilejowana aplikacja (np. Asystent Google lub
usługa ułatwień dostępu) miała uprawnienie
android.permission.CAPTURE_AUDIO_HOTWORD i używała źródła dźwięku typu
HOTWORD. W takim przypadku inna aplikacja mogła rozpocząć nagrywanie. Gdy tak się stało, uprzywilejowana aplikacja została zamknięta, a nowa aplikacja przechwyciła dane wejściowe.
W Androidzie 9 wprowadzono jeszcze jedną zmianę: tylko aplikacje działające na pierwszym planie (lub usługa działająca na pierwszym planie) mogły przechwytywać dane wejściowe audio. Gdy aplikacja bez usługi działającej na pierwszym planie lub komponentu interfejsu działającego na pierwszym planie zaczęła przechwytywać dźwięk, aplikacja działała dalej, ale otrzymywała ciszę, nawet jeśli była jedyną aplikacją, która w tym czasie przechwytywała dźwięk.
Działanie w Androidzie 10
Przed Androidem 10 obowiązywała zasada „kto pierwszy, ten lepszy”. Gdy aplikacja zacznie przechwytywać dźwięk, żadna inna aplikacja nie będzie mogła uzyskać dostępu do danych wejściowych audio, dopóki aplikacja przechwytująca dźwięk nie przestanie tego robić.
Android 10 wprowadza schemat priorytetów, który może przełączać wejściowy strumień audio między aplikacjami podczas ich działania. W większości przypadków, jeśli nowa aplikacja uzyska dane wejściowe audio, aplikacja, która wcześniej przechwytywała dźwięk, będzie nadal działać, ale będzie otrzymywać ciszę. W niektórych przypadkach system może nadal dostarczać dźwięk do obu aplikacji. Różne scenariusze udostępniania opisujemy poniżej.
Ten schemat jest podobny do sposobu, w jaki aktywność audio obsługuje wiele aplikacji konkurujących o korzystanie z wyjścia audio. Aktywność audio jest jednak zarządzana przez programowe żądania uzyskania i zwolnienia aktywności audio, a opisany tutaj schemat przełączania danych wejściowych opiera się na zasadach priorytetów, które są stosowane automatycznie, gdy nowa aplikacja zaczyna przechwytywać dźwięk.
Na potrzeby przechwytywania dźwięku Android rozróżnia 2 rodzaje aplikacji:
- „Zwykłe” aplikacje są instalowane przez użytkownika.
- „Uprzywilejowane” aplikacje są wstępnie zainstalowane na urządzeniu. Należą do nich Asystent Google i wszystkie usługi ułatwień dostępu.
Ponadto aplikacja jest traktowana inaczej, jeśli używa źródła dźwięku "wrażliwego na prywatność"
: CAMCORDER lub VOICE_COMMUNICATION.
Reguły priorytetów dotyczące używania i udostępniania danych wejściowych audio są następujące:
- Aplikacje uprzywilejowane mają wyższy priorytet niż zwykłe aplikacje.
- Aplikacje z widocznymi interfejsami działającymi na pierwszym planie mają wyższy priorytet niż aplikacje działające w tle.
- Aplikacje przechwytujące dźwięk ze źródła wrażliwego na prywatność mają wyższy priorytet niż aplikacje, które tego nie robią.
- 2 zwykłe aplikacje nigdy nie mogą przechwytywać dźwięku w tym samym czasie.
- W niektórych sytuacjach uprzywilejowana aplikacja może udostępniać dane wejściowe audio innej aplikacji.
- Jeśli 2 aplikacje działające w tle o tym samym priorytecie przechwytują dźwięk, wyższy priorytet ma ta, która została uruchomiona jako ostatnia.
Scenariusze udostępniania
Gdy 2 aplikacje próbują przechwycić dźwięk, obie mogą otrzymywać sygnał wejściowy lub jedna z nich może otrzymywać ciszę.
Istnieją 4 główne scenariusze:
- Asystent + zwykła aplikacja
- Usługa ułatwień dostępu + zwykła aplikacja
- 2 zwykłe aplikacje
- Połączenie głosowe + zwykła aplikacja
Asystent + zwykła aplikacja
Asystent jest aplikacją uprzywilejowaną, ponieważ jest wstępnie zainstalowany i ma
rolę RoleManager.ROLE_ASSISTANT. Każda inna wstępnie zainstalowana aplikacja z tą rolą jest traktowana podobnie.
Android udostępnia wejściowy dźwięk zgodnie z tymi regułami:
Asystent może odbierać dźwięk (niezależnie od tego, czy działa na pierwszym planie, czy w tle), chyba że inna aplikacja korzystająca ze źródła dźwięku wrażliwego na prywatność już przechwytuje dźwięk.
Aplikacja odbiera dźwięk, chyba że Asystent ma widoczny komponent interfejsu na górze ekranu.
Pamiętaj, że obie aplikacje odbierają dźwięk tylko wtedy, gdy Asystent działa w tle, a druga aplikacja nie przechwytuje dźwięku ze źródła wrażliwego na prywatność.
Usługa ułatwień dostępu + zwykła aplikacja
An AccessibilityService wymaga ścisłej deklaracji.
Android udostępnia wejściowy dźwięk zgodnie z tymi regułami:
Jeśli interfejs usługi jest na wierzchu, zarówno usługa, jak i aplikacja otrzymują dane wejściowe audio. Takie działanie umożliwia korzystanie z funkcji takich jak sterowanie połączeniem głosowym lub nagrywaniem wideo za pomocą poleceń głosowych.
Jeśli usługa nie jest na wierzchu, ten przypadek jest traktowany jak zwykły przypadek 2 aplikacji opisany poniżej.
2 zwykłe aplikacje
Gdy 2 aplikacje przechwytują dźwięk jednocześnie, tylko 1 z nich otrzymuje dźwięk, a druga ciszę.
Android udostępnia wejściowy dźwięk zgodnie z tymi regułami:
- Jeśli żadna z aplikacji nie jest wrażliwa na prywatność, dźwięk otrzymuje aplikacja z interfejsem na wierzchu. Jeśli żadna z aplikacji nie ma interfejsu, dźwięk otrzymuje ta, która rozpoczęła przechwytywanie jako ostatnia.
- Jeśli jedna z aplikacji jest wrażliwa na prywatność, otrzymuje dźwięk, a druga ciszę, nawet jeśli ma interfejs na wierzchu lub rozpoczęła przechwytywanie jako ostatnia.
- Jeśli obie aplikacje są wrażliwe na prywatność, dźwięk otrzymuje aplikacja, która rozpoczęła przechwytywanie jako ostatnia, a druga ciszę.
Połączenie głosowe + zwykła aplikacja
Połączenie głosowe jest aktywne, jeśli tryb audio zwracany przez
AudioManager.getMode() to MODE_IN_CALL lub
MODE_IN_COMMUNICATION.
Android udostępnia wejściowy dźwięk zgodnie z tymi regułami:
- Połączenie zawsze otrzymuje dźwięk.
- Aplikacja może przechwytywać dźwięk, jeśli jest usługą ułatwień dostępu.
Aplikacja może przechwytywać połączenie głosowe, jeśli jest aplikacją uprzywilejowaną (wstępnie zainstalowaną) z uprawnieniem
CAPTURE_AUDIO_OUTPUT.Aby przechwytywać połączenie głosowe (TX), połączenie przychodzące (RX) lub oba te połączenia, aplikacja musi określić źródła dźwięku
MediaRecorder.AudioSource.VOICE_UPLINKlubMediaRecorder.AudioSource.VOICE_DOWNLINKi/lub urządzenieAudioDeviceInfo.TYPE_TELEPHONY.
Działanie w Androidzie 11
Android 11 (poziom 30 interfejsu API) stosuje opisany powyżej schemat priorytetów z Androida 10. Zawiera też nowe metody w AudioRecord, MediaRecorder i AAudioStream, które umożliwiają włączanie i wyłączanie możliwości jednoczesnego przechwytywania dźwięku niezależnie od wybranego przypadku użycia.
Nowe metody to:
AudioRecord.Builder.setPrivacySensitive()AudioRecord.isPrivacySensitive()MediaRecorder.setPrivacySensitive()MediaRecorder.isPrivacySensitive()AAudioStreamBuilder_setPrivacySensitive()AAudioStream_isPrivacySensitive()
Gdy setPrivacySensitive() ma wartość true, przypadek użycia przechwytywania jest prywatny i nawet uprzywilejowany Asystent nie może przechwytywać dźwięku jednocześnie. To ustawienie zastępuje domyślne działanie, które zależy od źródła dźwięku. Na przykład VOICE_COMMUNICATION jest domyślnie prywatne, ale UNPROCESSED już nie.
Zmiany konfiguracji
Gdy kilka aplikacji przechwytuje dźwięk jednocześnie, tylko 1 lub 2 z nich są „aktywne” (otrzymują dźwięk), a pozostałe są wyciszone (otrzymują ciszę). Gdy aktywne aplikacje się zmieniają, platforma audio może ponownie skonfigurować ścieżki audio zgodnie z tymi regułami:
- Urządzenie wejściowe audio dla każdej aktywnej aplikacji może się zmienić (np. z wbudowanego mikrofonu na podłączony zestaw słuchawkowy Bluetooth).
- Włączone jest przetwarzanie wstępne powiązane z aktywną aplikacją o najwyższym priorytecie. Całe pozostałe przetwarzanie wstępne jest ignorowane.
Ponieważ aktywna aplikacja może zostać wyciszona, gdy aktywna stanie się aplikacja o wyższym priorytecie,
możesz zarejestrować AudioManager.AudioRecordingCallback w obiekcie
AudioRecord lub MediaRecorder, aby otrzymywać powiadomienia o zmianach
konfiguracji. Możliwe zmiany to:
- Wyciszenie lub wyłączenie wyciszenia przechwytywania
- Zmiana urządzenia
- Zmiana przetwarzania wstępnego
- Zmiana właściwości strumienia (częstotliwość próbkowania, maska kanału, format próbki)
Zanim rozpocznie się
przechwytywanie, musisz wywołać AudioRecord.registerAudioRecordingCallback(). Wywołanie zwrotne jest wykonywane tylko wtedy, gdy aplikacja odbiera dźwięk i nastąpi zmiana.
Metoda onRecordingConfigChanged() zwraca
AudioRecordingConfiguration zawierającą bieżący stan przechwytywania dźwięku.
Aby dowiedzieć się więcej o zmianie, użyj tych metod:
isClientSilenced()- Zwraca wartość true, jeśli dźwięk zwracany do klienta jest obecnie wyciszany z powodu zasad przechwytywania.
getAudioDevice()- Zwraca aktywne urządzenie audio.
getEffects()- Zwraca aktywny efekt przetwarzania wstępnego. Pamiętaj, że aktywny efekt może się różnić od efektów zwracanych przez
getClientEffects(), jeśli klient nie jest aktywną aplikacją o najwyższym priorytecie. getFormat()- Zwraca właściwości strumienia. Pamiętaj, że rzeczywiste dane audio odbierane przez klienta zawsze są zgodne z wymaganym formatem zwracanym przez
getClientFormat(). Platforma automatycznie przeprowadza niezbędne ponowne próbkowanie, konwersję kanału i formatu z formatu używanego w interfejsie sprzętowym na format określony przez klienta. AudioRecord.getActiveRecordingConfiguration()- Zwraca aktywną konfigurację nagrywania.
Ogólny widok wszystkich aktywnych nagrań na urządzeniu możesz uzyskać, wywołując
AudioManager.getActiveRecordingConfigurations().