Đầu vào âm thanh thường đến từ micrô tích hợp, micrô bên ngoài hoặc giao diện âm thanh được gắn vào thiết bị. Dữ liệu đầu vào âm thanh cũng có thể đến từ một cuộc trò chuyện qua điện thoại.
Đôi khi, hai hoặc nhiều ứng dụng có thể muốn "ghi lại" cùng một đầu vào âm thanh. Các luồng có thể đang thực hiện các tác vụ khác nhau. Ví dụ: một số ứng dụng nhận âm thanh có thể đang "ghi âm", chẳng hạn như một trình ghi âm giọng nói đơn giản, trong khi các ứng dụng khác có thể đang "nghe", chẳng hạn như Trợ lý Google hoặc một dịch vụ hỗ trợ tiếp cận phản hồi các lệnh thoại.
Trong cả hai trường hợp, các ứng dụng này đều muốn nhận dữ liệu đầu vào âm thanh. Trong trang này, chúng tôi sử dụng thuật ngữ "ghi lại" bất kể ứng dụng đang ghi âm hay chỉ nghe.
Nếu hai hoặc nhiều ứng dụng muốn ghi âm cùng một lúc, thì có thể xảy ra sự cố khi phân phối tín hiệu âm thanh từ cùng một nguồn đến tất cả các ứng dụng đó. Trang này mô tả cách hệ thống Android chia sẻ đầu vào âm thanh giữa nhiều ứng dụng ghi âm.
Hành vi trước Android 10
Trước Android 10, mỗi thời điểm chỉ có một ứng dụng có thể ghi lại luồng âm thanh đầu vào. Nếu một số ứng dụng đang ghi hoặc nghe âm thanh, thì ứng dụng của bạn có thể tạo đối tượng AudioRecord
, nhưng hệ thống sẽ trả về lỗi khi bạn gọi AudioRecord.startRecording()
và quá trình ghi sẽ không bắt đầu.
Có một ngoại lệ đối với quy tắc này là khi một ứng dụng đặc quyền (như Trợ lý Google hoặc dịch vụ hỗ trợ tiếp cận) có quyền android.permission.CAPTURE_AUDIO_HOTWORD
và sử dụng nguồn âm thanh thuộc loại HOTWORD
. Trong trường hợp này, một ứng dụng khác có thể bắt đầu ghi. Khi điều đó xảy ra, ứng dụng đặc quyền sẽ chấm dứt và ứng dụng mới sẽ ghi lại dữ liệu đầu vào.
Android 9 có thêm một thay đổi nữa: chỉ những ứng dụng chạy trên nền trước (hoặc một dịch vụ trên nền trước) mới có thể ghi lại đầu vào âm thanh. Khi một ứng dụng không có dịch vụ trên nền trước hoặc thành phần giao diện người dùng trên nền trước bắt đầu ghi lại, ứng dụng đó sẽ tiếp tục chạy nhưng không có âm thanh, ngay cả khi đó là ứng dụng duy nhất ghi lại âm thanh tại thời điểm đó.
Hành vi của Android 10
Hành vi trước Android 10 là "thứ tự đến trước được phục vụ trước". Sau khi một ứng dụng bắt đầu ghi âm, không ứng dụng nào khác có thể truy cập vào đầu vào âm thanh cho đến khi ứng dụng đang ghi âm dừng lại.
Android 10 áp dụng một lược đồ ưu tiên có thể chuyển đổi luồng âm thanh đầu vào giữa các ứng dụng trong khi các ứng dụng đó đang chạy. Trong hầu hết các trường hợp, nếu một ứng dụng mới thu nhận đầu vào âm thanh, thì ứng dụng đã ghi trước đó sẽ tiếp tục chạy nhưng không nhận được âm thanh. Trong một số trường hợp, hệ thống có thể tiếp tục phân phối âm thanh cho cả hai ứng dụng. Dưới đây là nội dung giải thích về các trường hợp chia sẻ.
Lược đồ này tương tự như cách tiêu điểm âm thanh xử lý nhiều ứng dụng cạnh tranh để sử dụng đầu ra âm thanh. Tuy nhiên, quyền phát âm thanh được quản lý bằng các yêu cầu có lập trình để lấy và nhả quyền phát, trong khi lược đồ chuyển đổi đầu vào được mô tả ở đây dựa trên chính sách ưu tiên được áp dụng tự động bất cứ khi nào một ứng dụng mới bắt đầu ghi âm thanh.
Để ghi âm, Android phân biệt hai loại ứng dụng:
- Ứng dụng "thông thường" do người dùng cài đặt.
- Ứng dụng "có đặc quyền" được cài đặt sẵn trên thiết bị. Các dịch vụ này bao gồm Trợ lý Google và tất cả dịch vụ hỗ trợ tiếp cận.
Ngoài ra, một ứng dụng sẽ được xử lý theo cách khác nếu sử dụng nguồn âm thanh "nhạy cảm về quyền riêng tư": CAMCORDER
hoặc VOICE_COMMUNICATION
.
Sau đây là các quy tắc ưu tiên để sử dụng và chia sẻ dữ liệu đầu vào âm thanh:
- Ứng dụng đặc quyền có mức độ ưu tiên cao hơn ứng dụng thông thường.
- Ứng dụng có giao diện người dùng trên nền trước hiển thị có mức độ ưu tiên cao hơn ứng dụng chạy ở chế độ nền.
- Ứng dụng ghi âm từ nguồn nhạy cảm về quyền riêng tư có mức độ ưu tiên cao hơn so với ứng dụng không ghi âm từ nguồn đó.
- Hai ứng dụng thông thường không bao giờ thu được âm thanh cùng một lúc.
- Trong một số trường hợp, một ứng dụng đặc quyền có thể chia sẻ đầu vào âm thanh với một ứng dụng khác.
- Nếu hai ứng dụng nền có cùng mức độ ưu tiên đang ghi âm, thì ứng dụng bắt đầu gần đây nhất sẽ có mức độ ưu tiên cao hơn.
Tình huống chia sẻ
Khi hai ứng dụng đang cố gắng ghi âm, cả hai ứng dụng đều có thể nhận được tín hiệu đầu vào hoặc một trong hai ứng dụng có thể nhận được âm thanh im lặng.
Có 4 trường hợp chính:
- Trợ lý + ứng dụng thông thường
- Dịch vụ hỗ trợ tiếp cận + ứng dụng thông thường
- Hai ứng dụng thông thường
- Cuộc gọi thoại + ứng dụng thông thường
Trợ lý + ứng dụng thông thường
Trợ lý là một ứng dụng đặc quyền vì được cài đặt sẵn và giữ vai trò RoleManager.ROLE_ASSISTANT
.
Mọi ứng dụng cài đặt sẵn khác có vai trò này đều được xử lý tương tự.
Android chia sẻ âm thanh đầu vào theo các quy tắc sau:
Trợ lý có thể nhận âm thanh (bất kể âm thanh đó ở nền trước hay nền sau) trừ phi một ứng dụng khác đang ghi lại âm thanh nhạy cảm về quyền riêng tư.
Ứng dụng sẽ nhận được âm thanh trừ phi Trợ lý có thành phần giao diện người dùng hiển thị ở đầu màn hình.
Xin lưu ý rằng cả hai ứng dụng chỉ nhận được âm thanh khi Trợ lý đang chạy ở chế độ nền và ứng dụng kia không ghi lại từ nguồn âm thanh nhạy cảm về quyền riêng tư.
Dịch vụ hỗ trợ tiếp cận + ứng dụng thông thường
AccessibilityService
yêu cầu khai báo nghiêm ngặt.
Android chia sẻ âm thanh đầu vào theo các quy tắc sau:
Nếu giao diện người dùng của dịch vụ nằm ở trên cùng, thì cả dịch vụ và ứng dụng đều nhận được đầu vào âm thanh. Hành vi này cung cấp chức năng như điều khiển cuộc gọi thoại hoặc quay video bằng lệnh thoại.
Nếu dịch vụ không ở trên cùng, trường hợp này sẽ được xử lý như trường hợp hai ứng dụng thông thường bên dưới.
Hai ứng dụng thông thường
Khi 2 ứng dụng chụp đồng thời, chỉ một ứng dụng nhận được âm thanh còn ứng dụng còn lại chuyển sang chế độ im lặng.
Android chia sẻ âm thanh đầu vào theo các quy tắc sau:
- Nếu không có ứng dụng nào nhạy cảm về quyền riêng tư, thì ứng dụng có giao diện người dùng ở trên cùng sẽ nhận được âm thanh. Nếu cả hai ứng dụng đều không có giao diện người dùng, thì ứng dụng bắt đầu quay video gần đây nhất sẽ nhận được âm thanh.
- Nếu một trong các ứng dụng nhạy cảm về quyền riêng tư, thì ứng dụng đó sẽ nhận được âm thanh và ứng dụng còn lại sẽ bị tắt tiếng ngay cả khi ứng dụng đó có giao diện người dùng ở trên cùng hoặc bắt đầu ghi âm gần đây hơn.
- Nếu cả hai ứng dụng đều nhạy cảm với quyền riêng tư, thì ứng dụng bắt đầu ghi âm gần đây nhất sẽ nhận được âm thanh và ứng dụng còn lại sẽ nhận được âm thanh im lặng.
Cuộc gọi thoại + ứng dụng thông thường
Cuộc gọi thoại đang hoạt động nếu chế độ âm thanh do AudioManager.getMode()
trả về là MODE_IN_CALL
hoặc MODE_IN_COMMUNICATION
.
Android chia sẻ âm thanh đầu vào theo các quy tắc sau:
- Cuộc gọi luôn nhận được âm thanh.
- Ứng dụng có thể ghi âm nếu là một dịch vụ hỗ trợ tiếp cận.
Ứng dụng có thể ghi lại cuộc gọi thoại nếu đó là ứng dụng đặc quyền (được cài đặt sẵn) có quyền
CAPTURE_AUDIO_OUTPUT
.Để ghi lại đường truyền lên (TX), đường truyền xuống (RX) hoặc cả hai của cuộc gọi thoại, ứng dụng phải chỉ định nguồn âm thanh
MediaRecorder.AudioSource.VOICE_UPLINK
hoặcMediaRecorder.AudioSource.VOICE_DOWNLINK
và/hoặc thiết bịAudioDeviceInfo.TYPE_TELEPHONY
.
Hành vi của Android 11
Android 11 (API cấp 30) tuân theo lược đồ mức độ ưu tiên của Android 10 được mô tả ở trên. Thư viện này cũng cung cấp các phương thức mới trong AudioRecord
, MediaRecorder
và AAudioStream
để bật và tắt khả năng ghi âm đồng thời, bất kể trường hợp sử dụng đã chọn.
Các phương thức mới là:
AudioRecord.Builder.setPrivacySensitive()
AudioRecord.isPrivacySensitive()
MediaRecorder.setPrivacySensitive()
MediaRecorder.isPrivacySensitive()
AAudioStreamBuilder_setPrivacySensitive()
AAudioStream_isPrivacySensitive()
Khi setPrivacySensitive()
là true
, trường hợp sử dụng chụp sẽ ở chế độ riêng tư và ngay cả Trợ lý có đặc quyền cũng không thể chụp đồng thời. Chế độ cài đặt này sẽ ghi đè hành vi mặc định tuỳ thuộc vào nguồn âm thanh. Ví dụ: Theo mặc định, VOICE_COMMUNICATION
là riêng tư nhưng UNPROCESSED
thì không.
Các thay đổi về cấu hình
Khi có nhiều ứng dụng cùng lúc đang ghi âm, chỉ một hoặc hai ứng dụng trong số đó là "đang hoạt động" (nhận âm thanh); các ứng dụng khác bị tắt tiếng (nhận âm thanh im lặng). Khi các ứng dụng đang hoạt động thay đổi, khung âm thanh có thể định cấu hình lại các đường dẫn âm thanh theo những quy tắc sau:
- Thiết bị đầu vào âm thanh cho mỗi ứng dụng đang hoạt động có thể thay đổi (ví dụ: từ micrô tích hợp sang tai nghe Bluetooth được đính kèm).
- Đã bật tính năng xử lý trước liên kết với ứng dụng đang hoạt động có mức độ ưu tiên cao nhất. Tất cả các hoạt động xử lý trước khác đều bị bỏ qua.
Vì một ứng dụng đang hoạt động có thể bị tắt tiếng khi một ứng dụng có mức độ ưu tiên cao hơn trở nên hoạt động, nên bạn có thể đăng ký một AudioManager.AudioRecordingCallback trên đối tượng AudioRecord
hoặc MediaRecorder
để được thông báo khi cấu hình thay đổi.
Những thay đổi có thể xảy ra có thể là:
- Quay video có tắt tiếng hoặc không tắt tiếng
- Đã thay đổi thiết bị
- Đã thay đổi quy trình xử lý trước
- Các thuộc tính của luồng đã thay đổi (tốc độ lấy mẫu, mặt nạ kênh, định dạng mẫu)
Bạn phải gọi AudioRecord.registerAudioRecordingCallback()
trước khi bắt đầu chụp.
Lệnh gọi lại chỉ được thực thi khi ứng dụng đang nhận âm thanh và có thay đổi xảy ra.
Phương thức onRecordingConfigChanged()
trả về một AudioRecordingConfiguration
chứa trạng thái ghi âm hiện tại. Hãy sử dụng các phương thức sau để tìm hiểu về thay đổi này:
isClientSilenced()
- Trả về giá trị true nếu âm thanh trả về máy khách hiện đang bị tắt tiếng do chính sách ghi âm.
getAudioDevice()
- Trả về thiết bị âm thanh đang hoạt động.
getEffects()
- Trả về hiệu ứng xử lý trước đang hoạt động. Xin lưu ý rằng hiệu ứng đang hoạt động có thể không giống với hiệu ứng do
getClientEffects()
trả về nếu ứng dụng khách không phải là ứng dụng đang hoạt động có mức độ ưu tiên cao nhất. getFormat()
- Trả về các thuộc tính của luồng. Xin lưu ý rằng dữ liệu âm thanh thực tế mà ứng dụng nhận được luôn tuân theo định dạng bắt buộc do
getClientFormat()
trả về. Khung này tự động thực hiện việc lấy mẫu lại, kênh và chuyển đổi định dạng cần thiết từ định dạng được sử dụng tại giao diện phần cứng sang định dạng do ứng dụng chỉ định. AudioRecord.getActiveRecordingConfiguration()
.- Trả về cấu hình quay video đang hoạt động.
Bạn có thể xem thông tin tổng quan về tất cả bản ghi đang hoạt động trên thiết bị bằng cách gọi AudioManager.getActiveRecordingConfigurations()
.