กำลังแชร์อินพุตเสียง

อินพุตเสียงมักมาจากไมโครโฟนในตัว ไมโครโฟนภายนอก หรืออินเทอร์เฟซเสียงที่เชื่อมต่อกับอุปกรณ์ อินพุตเสียงอาจมาจากการสนทนาทางโทรศัพท์ด้วย

บางครั้งแอปตั้งแต่ 2 แอปขึ้นไปอาจต้องการ "บันทึก" อินพุตเสียงเดียวกัน เนื่องจากอาจทํางานคนละอย่าง ตัวอย่างเช่น แอปบางแอปที่รับเสียงอาจ "บันทึก" เสียง เช่น เครื่องอัดเสียงแบบธรรมดา ขณะที่แอปอื่นๆ อาจ "ฟัง" เสียง เช่น Google Assistant หรือบริการการช่วยเหลือพิเศษที่ตอบสนองต่อคำสั่งเสียง

ไม่ว่าในกรณีใด แอปเหล่านี้ก็ต้องการรับอินพุตเสียง ตลอดทั้งหน้านี้ เราจะใช้คำว่า "บันทึก" ไม่ว่าแอปจะบันทึกหรือแค่ฟัง

หากแอป 2 แอปขึ้นไปต้องการบันทึกเสียงพร้อมกัน ก็อาจมีปัญหาในการส่งสัญญาณเสียงจากแหล่งที่มาเดียวกันไปยังแอปทั้งหมด หน้านี้อธิบายวิธีระบบ Android แชร์อินพุตเสียงระหว่างแอปหลายแอปที่บันทึกเสียง

ลักษณะการทํางานก่อน Android 10

ก่อนที่จะมี Android 10 แอปหนึ่งๆ จะบันทึกสตรีมเสียงอินพุตได้ทีละรายการเท่านั้น หากแอปบางแอปบันทึกหรือฟังเสียงอยู่แล้ว แอปของคุณอาจสร้างออบเจ็กต์ AudioRecord ได้ แต่ระบบจะแสดงข้อผิดพลาดเมื่อคุณเรียกใช้ AudioRecord.startRecording() และระบบจะไม่เริ่มบันทึก

ข้อยกเว้นหนึ่งของกฎนี้เกิดขึ้นเมื่อแอปที่มีสิทธิ์ (เช่น Google Assistant หรือบริการการช่วยเหลือพิเศษ) มีสิทธิ์ android.permission.CAPTURE_AUDIO_HOTWORD และใช้แหล่งที่มาของเสียงประเภท HOTWORD ในกรณีนี้ แอปอื่นอาจเริ่มบันทึกได้ เมื่อเกิดเหตุการณ์ดังกล่าว แอปที่มีสิทธิ์จะสิ้นสุดลงและแอปใหม่จะบันทึกอินพุต

การเปลี่ยนแปลงอีกอย่างหนึ่งที่เพิ่มเข้ามาใน Android 9 คือมีเพียงแอปที่ทำงานอยู่เบื้องหน้า (หรือบริการที่ทำงานอยู่เบื้องหน้า) เท่านั้นที่บันทึกอินพุตเสียงได้ เมื่อแอปที่ไม่มีบริการที่ทำงานอยู่เบื้องหน้าหรือคอมโพเนนต์ UI ที่ทำงานอยู่เบื้องหน้าเริ่มบันทึก แอปจะยังคงทำงานต่อไปแต่ได้รับเสียงที่เงียบสนิท แม้ว่าจะเป็นแอปเดียวที่บันทึกเสียงในเวลานั้นก็ตาม

ลักษณะการทํางานของ Android 10

ลักษณะการทำงานก่อน Android 10 คือ "มาก่อนได้ก่อน" เมื่อแอปเริ่มบันทึกเสียง แอปอื่นๆ จะเข้าถึงอินพุตเสียงไม่ได้จนกว่าแอปที่บันทึกเสียงจะหยุด

Android 10 ใช้รูปแบบลำดับความสำคัญที่สามารถสลับสตรีมเสียงอินพุตระหว่างแอปขณะที่แอปทำงานอยู่ ในกรณีส่วนใหญ่ หากแอปใหม่ได้รับอินพุตเสียง แอปที่บันทึกก่อนหน้านี้จะยังคงทำงานต่อไป แต่จะได้รับเสียงเงียบ ในบางกรณี ระบบอาจส่งเสียงไปยังทั้ง 2 แอปได้ สถานการณ์การแชร์ต่างๆ มีคำอธิบายอยู่ด้านล่าง

รูปแบบนี้คล้ายกับวิธีที่โฟกัสเสียงจัดการกับแอปหลายแอปที่แย่งกันใช้เอาต์พุตเสียง อย่างไรก็ตาม โฟกัสเสียงจะจัดการโดยคำขอแบบเป็นโปรแกรมเพื่อรับและปล่อยโฟกัส ส่วนรูปแบบการเปลี่ยนอินพุตที่อธิบายไว้ที่นี่จะอิงตามนโยบายการจัดลำดับความสำคัญที่มีผลโดยอัตโนมัติเมื่อแอปใหม่เริ่มบันทึกเสียง

Android จะแยกแอปออกเป็น 2 ประเภทสำหรับการบันทึกเสียง ดังนี้

  • แอป "ธรรมดา" ติดตั้งโดยผู้ใช้
  • แอป "ที่มีสิทธิ์" จะติดตั้งมาล่วงหน้าในอุปกรณ์ ซึ่งรวมถึง Google Assistant และบริการการช่วยเหลือพิเศษทั้งหมด

นอกจากนี้ ระบบจะจัดการแอปในลักษณะที่แตกต่างกันหากแอปใช้แหล่งที่มาของเสียงที่ "มีความละเอียดอ่อนด้านความเป็นส่วนตัว" ซึ่งได้แก่ CAMCORDER หรือ VOICE_COMMUNICATION

กฎการจัดลําดับความสําคัญสําหรับการใช้และการแชร์อินพุตเสียงมีดังนี้

  • แอปที่มีสิทธิ์จะมีลำดับความสำคัญสูงกว่าแอปทั่วไป
  • แอปที่มี UI เบื้องหน้ามองเห็นได้จะมีลำดับความสำคัญสูงกว่าแอปเบื้องหลัง
  • แอปที่บันทึกเสียงจากแหล่งที่มาที่ละเอียดอ่อนด้านความเป็นส่วนตัวจะมีลำดับความสำคัญสูงกว่าแอปที่ไม่ได้บันทึกเสียงจากแหล่งที่มาดังกล่าว
  • แอปทั่วไป 2 แอปจะบันทึกเสียงพร้อมกันไม่ได้
  • ในบางสถานการณ์ แอปที่มีสิทธิ์สามารถแชร์อินพุตเสียงกับแอปอื่นได้
  • หากแอปเบื้องหลัง 2 แอปที่มีลำดับความสำคัญเดียวกันกำลังบันทึกเสียงอยู่ แอปที่เริ่มทำงานล่าสุดจะมีลำดับความสำคัญสูงกว่า

สถานการณ์การแชร์

เมื่อแอป 2 แอปพยายามบันทึกเสียง แอปทั้ง 2 แอปอาจรับสัญญาณอินพุตได้ หรือแอปใดแอปหนึ่งอาจได้รับเสียงที่เงียบ

สถานการณ์หลักๆ มี 4 รูปแบบดังนี้

  • Assistant + แอปทั่วไป
  • บริการการช่วยเหลือพิเศษ + แอปทั่วไป
  • แอปทั่วไป 2 แอป
  • การโทรด้วยเสียง + แอปทั่วไป

Assistant + แอปทั่วไป

Assistant เป็นแอปที่มีสิทธิ์เนื่องจากติดตั้งไว้ล่วงหน้าและมีบทบาท RoleManager.ROLE_ASSISTANT แอปอื่นๆ ที่ติดตั้งไว้ล่วงหน้าซึ่งมีบทบาทนี้จะได้รับการประมวลผลในลักษณะเดียวกัน

Android จะแชร์เสียงอินพุตตามกฎต่อไปนี้

  • Assistant สามารถรับเสียงได้ (ไม่ว่าจะอยู่เบื้องหน้าหรือเบื้องหลัง) เว้นแต่ว่าแอปอื่นที่ใช้แหล่งที่มาของเสียงที่ละเอียดอ่อนด้านความเป็นส่วนตัวจะบันทึกเสียงอยู่

  • แอปจะรับเสียง เว้นแต่ว่า Assistant จะมีคอมโพเนนต์ UI ที่มองเห็นได้บนหน้าจอ

โปรดทราบว่าทั้ง 2 แอปจะได้รับเสียงเฉพาะเมื่อ Assistant ทำงานอยู่เบื้องหลังและอีกแอปไม่ได้บันทึกจากแหล่งที่มาของเสียงที่มีความละเอียดอ่อนด้านความเป็นส่วนตัว

บริการการช่วยเหลือพิเศษ + แอปทั่วไป

AccessibilityServiceต้องใช้ประกาศที่เข้มงวด

Android จะแชร์เสียงอินพุตตามกฎต่อไปนี้

  • หาก UI ของบริการอยู่ด้านบน ทั้งบริการและแอปจะได้รับอินพุตเสียง ลักษณะการทำงานนี้มีฟังก์ชันการทำงานต่างๆ เช่น การควบคุมการโทรด้วยเสียงหรือการบันทึกวิดีโอด้วยคำสั่งเสียง

  • หากบริการไม่ได้อยู่ด้านบน ระบบจะถือว่ากรณีนี้เหมือนกับกรณีแอป 2 แอปทั่วไปด้านล่าง

แอปทั่วไป 2 แอป

เมื่อแอป 2 แอปบันทึกพร้อมกัน จะมีเพียงแอปเดียวที่รับเสียง ส่วนอีกแอปจะรับเสียงที่เงียบ

Android จะแชร์เสียงอินพุตตามกฎต่อไปนี้

  • หากแอปใดแอปหนึ่งไม่เกี่ยวข้องกับความเป็นส่วนตัว แอปที่มี UI อยู่ด้านบนจะได้รับเสียง หากไม่มีแอปใดมีแอป UI เลย แอปที่เริ่มบันทึกล่าสุดจะได้รับเสียง
  • หากแอปใดแอปหนึ่งมีความละเอียดอ่อนด้านความเป็นส่วนตัว แอปนั้นจะรับเสียง ส่วนแอปอื่นจะเงียบแม้ว่าจะมี UI อยู่ด้านบนหรือเริ่มบันทึกเสียงเมื่อเร็วๆ นี้ก็ตาม
  • หากทั้ง 2 แอปมีความละเอียดอ่อนด้านความเป็นส่วนตัว แอปที่เริ่มบันทึกล่าสุดจะได้รับเสียง ส่วนอีกแอปจะได้ยินเสียงเงียบ

การโทรด้วยเสียง + แอปทั่วไป

การโทรด้วยเสียงจะทำงานอยู่หากโหมดเสียงที่ AudioManager.getMode() แสดงผลเป็น MODE_IN_CALL หรือ MODE_IN_COMMUNICATION

Android จะแชร์เสียงอินพุตตามกฎต่อไปนี้

ลักษณะการทํางานของ Android 11

Android 11 (API ระดับ 30) ใช้รูปแบบลําดับความสําคัญของ Android 10 ที่อธิบายไว้ข้างต้น นอกจากนี้ ยังมีเมธอดใหม่ใน AudioRecord, MediaRecorder และ AAudioStream ที่เปิดและปิดใช้ความสามารถในการบันทึกเสียงพร้อมกัน ไม่ว่าจะใช้ Use Case ใดก็ตาม

โดยวิธีการใหม่มีดังนี้

เมื่อ setPrivacySensitive() เป็น true กรณีการใช้งานการบันทึกจะเป็นแบบส่วนตัว และแม้แต่ Assistant ที่มีสิทธิ์ก็ไม่สามารถบันทึกพร้อมกันได้ การตั้งค่านี้จะลบล้างลักษณะการทำงานเริ่มต้นซึ่งขึ้นอยู่กับแหล่งที่มาของเสียง ตัวอย่างเช่น VOICE_COMMUNICATION เป็นส่วนตัวโดยค่าเริ่มต้น แต่ UNPROCESSED ไม่เป็น

การเปลี่ยนแปลงการกําหนดค่า

เมื่อแอปหลายแอปบันทึกเสียงพร้อมกัน จะมีเพียง 1 หรือ 2 แอปเท่านั้นที่ "ทำงานอยู่" (รับเสียง) ส่วนแอปอื่นๆ จะปิดเสียง (รับเสียงเงียบ) เมื่อแอปที่ใช้งานอยู่มีการเปลี่ยนแปลง เฟรมเวิร์กเสียงอาจกำหนดค่าเส้นทางเสียงใหม่ตามกฎต่อไปนี้

  • อุปกรณ์อินพุตเสียงสำหรับแอปที่ใช้งานอยู่แต่ละแอปอาจเปลี่ยนแปลง (เช่น จากไมโครโฟนในตัวเป็นชุดหูฟังบลูทูธที่เชื่อมต่ออยู่)
  • เปิดใช้การประมวลผลข้อมูลล่วงหน้าที่เชื่อมโยงกับแอปที่ใช้งานอยู่ซึ่งมีลําดับความสําคัญสูงสุด ระบบจะไม่สนใจการประมวลผลล่วงหน้าอื่นๆ ทั้งหมด

เนื่องจากแอปที่ใช้งานอยู่อาจถูกปิดเสียงเมื่อแอปที่มีลำดับความสำคัญสูงกว่าเริ่มทำงาน คุณจึงลงทะเบียน AudioManager.AudioRecordingCallback ในออบเจ็กต์ AudioRecord หรือ MediaRecorder เพื่อรับการแจ้งเตือนเมื่อการกําหนดค่ามีการเปลี่ยนแปลง การเปลี่ยนแปลงที่อาจเกิดขึ้นมีดังนี้

  • บันทึกเสียงที่ปิดเสียงไว้หรือไม่ได้ปิดเสียงไว้
  • เปลี่ยนอุปกรณ์แล้ว
  • เปลี่ยนการประมวลผลข้อมูลล่วงหน้า
  • เปลี่ยนพร็อพเพอร์ตี้สตรีม (อัตราการสุ่มตัวอย่าง มาสก์ช่อง รูปแบบตัวอย่าง)

คุณต้องเรียกใช้ AudioRecord.registerAudioRecordingCallback() ก่อนเริ่มการจับภาพ ระบบจะเรียกใช้การเรียกกลับก็ต่อเมื่อแอปรับเสียงและเกิดการเปลี่ยนแปลงเท่านั้น

เมธอด onRecordingConfigChanged() จะแสดงผล AudioRecordingConfiguration ที่มีสถานะการบันทึกเสียงปัจจุบัน ใช้วิธีต่อไปนี้เพื่อดูข้อมูลเกี่ยวกับการเปลี่ยนแปลง

isClientSilenced()
แสดงผลเป็น "จริง" หากเสียงที่ส่งกลับไปยังไคลเอ็นต์ถูกปิดเสียงอยู่เนื่องจากนโยบายการบันทึก
getAudioDevice()
แสดงอุปกรณ์เสียงที่ใช้งานอยู่
getEffects()
แสดงผลเอฟเฟกต์การประมวลผลข้อมูลล่วงหน้าที่ใช้งานอยู่ โปรดทราบว่าผลลัพธ์ที่ใช้งานอยู่อาจไม่เหมือนกับผลลัพธ์ที่ getClientEffects() แสดง หากไคลเอ็นต์ไม่ใช่แอปที่ใช้งานอยู่ซึ่งมีลําดับความสําคัญสูงสุด
getFormat()
แสดงผลพร็อพเพอร์ตี้สตรีม โปรดทราบว่าข้อมูลเสียงจริงที่ได้รับโดยไคลเอ็นต์จะเป็นไปตามรูปแบบที่จำเป็นซึ่ง getClientFormat() แสดงผลเสมอ เฟรมเวิร์กจะทำการแปลงที่จำเป็น เช่น การสุ่มตัวอย่างอีกครั้ง ช่อง และรูปแบบโดยอัตโนมัติจากรูปแบบที่ใช้ในอินเทอร์เฟซฮาร์ดแวร์เป็นรูปแบบที่ลูกค้าระบุ
AudioRecord.getActiveRecordingConfiguration()
แสดงผลการกำหนดค่าการบันทึกที่ใช้งานอยู่

คุณดูภาพรวมทั่วไปของการบันทึกที่ใช้งานอยู่ทั้งหมดในอุปกรณ์ได้โดยโทรไปที่ AudioManager.getActiveRecordingConfigurations()