Dźwięk wejściowy pochodzi 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 co najmniej 2 aplikacje mogą chcieć „przechwycić” to samo wejście audio. Mogą wykonywać różne zadania. Na przykład niektóre aplikacje, które odbierają dźwięk, mogą „nagrywać”, np. prosty dyktafon, a inne mogą „słuchać”, np. Asystent Google lub usługa ułatwień dostępu, która reaguje na polecenia głosowe.
W obu przypadkach aplikacje te chcą otrzymywać dane wejściowe audio. Na tej stronie używamy terminu „przechwytywanie” niezależnie od tego, czy aplikacja nagrywa, czy tylko słucha.
Jeśli 2 lub więcej aplikacji chce jednocześnie przechwytywać dźwięk, może wystąpić problem z dostarczaniem 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 wielu aplikacjom, które rejestrują dźwięk.
Działanie w przypadku wersji Androida starszych niż 10
W Androidzie 10 i starszych wersjach strumień dźwięku wejściowego mógł być przechwytywany tylko przez 1 aplikację naraz. Jeśli inna aplikacja nagrywała lub odtwarzała dźwięk, Twoja aplikacja mogła utworzyć obiekt AudioRecord
, ale po wywołaniu funkcji AudioRecord.startRecording()
zwracany był błąd i nagrywanie nie było rozpoczynane.
Wyjątkiem od tej reguły była sytuacja, w której uprzywilejowana aplikacja (np. Asystent Google lub usługa ułatwień dostępu) miała uprawnienia android.permission.CAPTURE_AUDIO_HOTWORD
i korzystała ze źródła dźwięku typu HOTWORD
. W takim przypadku nagrywanie może rozpocząć inna aplikacja. Gdy to się stało, aplikacja z uprawnieniami została zamknięta, a nowa aplikacja przejęła dane wejściowe.
W Androidzie 9 wprowadziliśmy kolejną zmianę: tylko aplikacje działające na pierwszym planie (lub usługa działająca na pierwszym planie) mogą przechwytywać dźwięk. Gdy aplikacja bez usługi na pierwszym planie lub komponentu interfejsu na pierwszym planie zaczynała rejestrować dźwięk, nadal działała, ale otrzymywała ciszę, nawet jeśli była jedyną aplikacją, która w tym czasie rejestrowała dźwięk.
Działanie Androida 10
W przypadku Androida 10 i starszych wersji obowiązuje zasada „kto pierwszy, ten lepszy”. Gdy aplikacja zacznie przechwytywać dźwięk, żadna inna aplikacja nie będzie miała dostępu do wejścia audio, dopóki aplikacja przechwytująca dźwięk nie zakończy tego procesu.
Android 10 wprowadza schemat priorytetów, który może przełączać strumień dźwięku wejściowego między aplikacjami podczas ich działania. W większości przypadków, jeśli nowa aplikacja uzyska dostęp do wejścia audio, poprzednio nagrywająca aplikacja będzie nadal działać, ale będzie odbierać ciszę. W niektórych przypadkach system może nadal przesyłać dźwięk do obu aplikacji. Poniżej znajdziesz opis różnych scenariuszy udostępniania.
Ten schemat jest podobny do sposobu, w jaki fokus audio obsługuje wiele aplikacji, które konkurują o korzystanie z wyjścia audio. Fokus dźwięku jest jednak zarządzany przez programowe żądania uzyskania i zwolnienia fokusu, a opisany tutaj schemat przełączania wejścia opiera się na zasadach priorytetów, które są stosowane automatycznie, gdy nowa aplikacja zaczyna przechwytywać dźwięk.
Na potrzeby rejestrowania dźwięku Android rozróżnia 2 rodzaje aplikacji:
- „Zwykłe” aplikacje są instalowane przez użytkownika.
- Aplikacje „uprzywilejowane” są wstępnie zainstalowane na urządzeniu. Obejmują one Asystenta Google i wszystkie usługi ułatwień dostępu.
Aplikacja jest traktowana inaczej, jeśli korzysta ze źródła dźwięku „wrażliwego na prywatność”: CAMCORDER
lub VOICE_COMMUNICATION
.
Reguły priorytetyzacji 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 użytkownika na pierwszym planie mają wyższy priorytet niż aplikacje działające w tle.
- Aplikacje, które rejestrują dźwięk ze źródła wrażliwego z punktu widzenia prywatności, mają wyższy priorytet niż aplikacje, które tego nie robią.
- Dwie zwykłe aplikacje nie mogą jednocześnie rejestrować dźwięku.
- 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 rejestrują 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ą odbierać sygnał wejściowy lub jedna z nich może odbierać 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 to aplikacja z podwyższonymi uprawnieniami, ponieważ jest fabrycznie zainstalowana i ma rolę RoleManager.ROLE_ASSISTANT
.
Wszystkie inne wstępnie zainstalowane aplikacje z tą rolą są traktowane podobnie.
Android udostępnia dane audio zgodnie z tymi regułami:
Asystent może odbierać dźwięk (niezależnie od tego, czy jest na pierwszym planie, czy w tle), chyba że inna aplikacja korzystająca z źródła dźwięku wrażliwego na prywatność już rejestruje dźwięk.
Aplikacja odbiera dźwięk, chyba że Asystent ma widoczny komponent interfejsu u góry ekranu.
Pamiętaj, że obie aplikacje otrzymują dźwięk tylko wtedy, gdy Asystent działa w tle, a druga aplikacja nie rejestruje dźwięku z źródła, które może zawierać dane wrażliwe.
Usługa ułatwień dostępu + zwykła aplikacja
AccessibilityService
wymaga ścisłej deklaracji.
Android udostępnia dane audio 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. Dzięki temu możesz sterować połączeniami głosowymi lub nagrywaniem wideo za pomocą poleceń głosowych.
Jeśli usługa nie jest na wierzchu, ten przypadek jest traktowany jak zwykły przypadek dwóch aplikacji opisany poniżej.
2 zwykłe aplikacje
Gdy 2 aplikacje nagrywają jednocześnie, tylko jedna z nich otrzymuje dźwięk, a druga ciszę.
Android udostępnia dane audio 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 jest przesyłany do tej, która ostatnio rozpoczęła nagrywanie.
- Jeśli jedna z aplikacji jest wrażliwa na prywatność, otrzymuje dźwięk, a druga ciszę, nawet jeśli ma interfejs u góry lub niedawno rozpoczęła nagrywanie.
- Jeśli obie aplikacje są wrażliwe na prywatność, dźwięk otrzymuje aplikacja, która rozpoczęła nagrywanie jako ostatnia, a druga aplikacja otrzymuje ciszę.
Połączenie głosowe + zwykła aplikacja
Połączenie głosowe jest aktywne, jeśli tryb audio zwrócony przez AudioManager.getMode()
to MODE_IN_CALL
lub MODE_IN_COMMUNICATION
.
Android udostępnia dane audio zgodnie z tymi regułami:
- Połączenie zawsze odbiera dźwięk.
- Aplikacja może rejestrować dźwięk, jeśli jest usługą ułatwień dostępu.
Aplikacja może rejestrować połączenia głosowe, jeśli jest aplikacją uprzywilejowaną (zainstalowaną fabrycznie) z uprawnieniami
CAPTURE_AUDIO_OUTPUT
.Aby rejestrować połączenia głosowe w kierunku do urządzenia (TX), z urządzenia (RX) lub w obu kierunkach, aplikacja musi określić źródła dźwięku
MediaRecorder.AudioSource.VOICE_UPLINK
lubMediaRecorder.AudioSource.VOICE_DOWNLINK
i/lub urządzenieAudioDeviceInfo.TYPE_TELEPHONY
.
Działanie Androida 11
Android 11 (poziom API 30) korzysta z opisanego powyżej schematu priorytetów Androida 10. Zawiera też nowe metody w AudioRecord
, MediaRecorder
i AAudioStream
, które umożliwiają i wyłączają możliwość jednoczesnego nagrywania 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 wartość setPrivacySensitive()
to true
, przypadek użycia przechwytywania jest prywatny i nawet uprzywilejowany Asystent nie może przechwytywać jednocześnie. To ustawienie zastępuje domyślne zachowanie, które zależy od źródła dźwięku. Na przykład VOICE_COMMUNICATION
jest domyślnie prywatny, ale UNPROCESSED
już nie.
Zmiany konfiguracji
Gdy kilka aplikacji jednocześnie przechwytuje dźwięk, tylko 1 lub 2 z nich są „aktywne” (odbierają dźwięk), a pozostałe są wyciszone (odbierają ciszę). Gdy aktywne aplikacje się zmienią, 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 mikrofonu wbudowanego na podłączony zestaw słuchawkowy Bluetooth).
- Wstępne przetwarzanie powiązane z aktywną aplikacją o najwyższym priorytecie jest włączone. Wszystkie inne etapy wstępnego przetwarzania są ignorowane.
Aktywna aplikacja może zostać wyciszona, gdy stanie się aktywna aplikacja o wyższym priorytecie. Aby otrzymywać powiadomienia o zmianach konfiguracji, możesz zarejestrować AudioManager.AudioRecordingCallback w obiekcie AudioRecord
lub MediaRecorder
.
Możliwe zmiany to:
- Zrobienie zdjęcia z wyciszonym lub niewyciszonym dźwiękiem
- Urządzenie zostało zmienione
- Zmiana przetwarzania wstępnego
- Zmieniono właściwości strumienia (częstotliwość próbkowania, maska kanału, format próbki)
Przed rozpoczęciem przechwytywania musisz wywołać funkcję AudioRecord.registerAudioRecordingCallback()
.
Funkcja zwrotna jest wykonywana tylko wtedy, gdy aplikacja odbiera dźwięk i nastąpi zmiana.
Metoda onRecordingConfigChanged()
zwraca obiekt AudioRecordingConfiguration
zawierający bieżący stan przechwytywania dźwięku. Aby dowiedzieć się więcej o zmianie, skorzystaj z tych metod:
isClientSilenced()
- Zwraca wartość „true”, jeśli dźwięk zwrócony do klienta jest obecnie wyciszony z powodu zasad przechwytywania.
getAudioDevice()
- Zwraca aktywne urządzenie audio.
getEffects()
- Zwraca aktywny efekt wstępnego przetwarzania. Pamiętaj, że aktywny efekt może nie być taki sam jak efekty zwracane 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 otrzymywane przez klienta są zawsze zgodne z wymaganym formatem zwracanym przez
getClientFormat()
. Platforma automatycznie przeprowadza niezbędne ponowne próbkowanie, konwersję kanałów i formatów 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ć, dzwoniąc pod numer AudioManager.getActiveRecordingConfigurations()
.