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

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

บางครั้งแอปตั้งแต่ 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 จะแชร์เสียงที่ป้อนตามกฎต่อไปนี้

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

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

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

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

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

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

เมธอดใหม่มีดังนี้

เมื่อ 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()