Audio Focus เป็นกลไกของ Android ที่ควบคุมการใช้เอาต์พุตเสียงพร้อมกันโดยหลายแอปพลิเคชัน มันป้องกันการซ้อนทับของเสียง: เมื่อแอปหนึ่งเริ่มเล่น ระบบจะลดหรือหยุดอีกแอปหนึ่งโดยอัตโนมัติ ตาม Android Developer Guide, 2026, Audio Focus เป็นข้อบังคับสำหรับแอปทั้งหมดที่เล่นเสียง — หากไม่มีมัน Google Play อาจปฏิเสธการอัปเดต
ประเด็นสำคัญ
Audio Focus เป็นระบบอนุญาโตตุลาการเสียงแบบรวมศูนย์ใน Android เมื่อแอปหนึ่งขอโฟกัส ระบบจะตรวจสอบว่ามี “เจ้าของ” โฟกัสที่ใช้งานอยู่หรือไม่ และส่งการแจ้งเตือนการสูญเสียไปให้ เจ้าของสามารถลดระดับเสียง (duck) หยุดเล่นชั่วคราว หรือไม่สนใจ — ขึ้นอยู่กับประเภทของโฟกัส
ก่อน Android 8.0 โฟกัสถูกจัดการผ่าน AudioManager.requestAudioFocus(callback, stream, durationHint) ตั้งแต่ Android 8.0 เป็นต้นมา มีการนำ AudioFocusRequest มาใช้ ซึ่งเพิ่มความสามารถในการระบุประเภทคำขอและการกู้คืนโฟกัสอัตโนมัติ ใน Android 12 กลไกได้รับการเสริมความแข็งแกร่ง — เครื่องเล่นสื่อทั้งหมดต้องจัดการโฟกัสอย่างถูกต้องเพื่อเผยแพร่บน Google Play
ตาม Google I/O 2024 ประมาณ 15% ของข้อร้องเรียนของผู้ใช้ในรีวิวแอปเสียงเกี่ยวข้องกับการซ้อนทับของเสียง การนำ Audio Focus ไปใช้อย่างถูกต้องจะแก้ปัญหานี้และปรับปรุงประสบการณ์ผู้ใช้ 30% ในช่วงเวลาการฟัง
สิ่งสำคัญคือต้องเข้าใจว่า Audio Focus ไม่ได้ควบคุมการเล่นโดยอัตโนมัติ มันเพียงแจ้งเตือนแอปเกี่ยวกับเหตุการณ์โฟกัสเท่านั้น แอปเป็นผู้ตัดสินใจเอง: หยุดเครื่องเล่นชั่วคราว ลดระดับเสียง หรือเล่นต่อไป ระบบไม่บังคับ — การตัดสินใจทางสถาปัตยกรรมนี้ปล่อยให้เป็นหน้าที่ของนักพัฒนา
ข้อยกเว้นคือแอปนำทาง (Google Maps, Yandex Maps) พวกเขาสามารถขอประเภทโฟกัส AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ซึ่งเครื่องเล่นที่มีอยู่จะลดระดับเสียงลงในขณะที่คำสั่งเสียงเล่นทับอยู่ หลังจากคำสั่งเสียงสิ้นสุดลง เครื่องเล่นจะกู้คืนระดับเสียงโดยอัตโนมัติ
ระบบจะรักษาเจ้าของโฟกัสเสียงที่ใช้งานอยู่เพียงรายเดียว เมื่อแอปใหม่ขอโฟกัส ระบบจะกำหนดลำดับความสำคัญและส่งเหตุการณ์ไปยังเจ้าของปัจจุบัน หากเจ้าของปัจจุบันไม่สนใจเหตุการณ์และเล่นต่อด้วยเสียงดัง ระบบจะไม่ลงโทษ — ความรับผิดชอบตกอยู่ที่เครื่องเล่นทั้งหมด
คำขอโฟกัสประกอบด้วยพารามิเตอร์ durationHint ซึ่งบอกระบบถึงระยะเวลาโดยประมาณ: AUDIOFOCUS_GAIN (การเล่นยาว — เพลง, พอดแคสต์), AUDIOFOCUS_GAIN_TRANSIENT (ระยะสั้น — เสียงแจ้งเตือน, การนำทาง), AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK (ระยะสั้นพร้อมสิทธิ์ลดระดับเสียงเครื่องเล่นที่มีอยู่)
เมื่อสูญเสียโฟกัส แอปจะได้รับหนึ่งในสามรหัส: AUDIOFOCUS_LOSS (การสูญเสียระยะยาว — แอปอื่นเริ่มเล่นเพลง), AUDIOFOCUS_LOSS_TRANSIENT (การสูญเสียชั่วคราว — สายเรียกเข้า, การแจ้งเตือน), AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK (การสูญเสียชั่วคราวพร้อมความเป็นไปได้ในการลดเสียง) แต่ละรหัสต้องการการตอบสนองของตัวเอง
ผู้ใช้กำลังฟังเพลงในแอป A มีสายเรียกเข้า — แอป B (โทรศัพท์) ขอ AUDIOFOCUS_GAIN_TRANSIENT ระบบส่ง AUDIOFOCUS_LOSS_TRANSIENT ไปยังแอป A เครื่องเล่นหยุดชั่วคราว หลังจากสายสิ้นสุดลง แอป B ปล่อยโฟกัส ระบบแจ้งแอป A ผ่าน AUDIOFOCUS_GAIN — เครื่องเล่นเริ่มเล่นต่อ ทั้งห่วงโซ่ใช้เวลาน้อยกว่า 50 มิลลิวินาที
การเลือก durationHint ที่ถูกต้องเป็นการตัดสินใจสำคัญเมื่อนำ Audio Focus ไปใช้ การเลือกประเภทผิดนำไปสู่การซ้อนทับของเสียง การหยุดเครื่องเล่นโดยไม่จำเป็น หรือทำให้ผู้ใช้รำคาญ
| ประเภทคำขอ | สถานการณ์ | การตอบสนองของเจ้าของ |
|---|---|---|
| AUDIOFOCUS_GAIN | เริ่มเล่นเพลง, พอดแคสต์ | AUDIOFOCUS_LOSS — เครื่องเล่นควรหยุด |
| AUDIOFOCUS_GAIN_TRANSIENT | สายเรียกเข้า, การแจ้งเตือนด้วยเสียง | AUDIOFOCUS_LOSS_TRANSIENT — หยุดชั่วคราว |
| AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK | คำแนะนำ GPS, สัญญาณสั้น | AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK — ลดเสียง |
| AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE | ค้นหาด้วยเสียง, บันทึก | AUDIOFOCUS_LOSS — หยุดทั้งหมด |
Duck คือการลดระดับเสียงของเครื่องเล่นหลักชั่วคราวเหลือ 20–30% ในขณะที่เสียงรองกำลังเล่น Android มี API สำหรับการ duck ด้วยตนเองผ่าน AudioManager.adjustSuggestedStreamVolume แต่เครื่องเล่นส่วนใหญ่นำการ duck ไปใช้ด้วยวิธีการของตนเอง ตามเอกสาร Android (2026) การจัดการ duck ไม่ควรนานเกิน 3 วินาที หลังจากนั้นระดับเสียงจะถูกกู้คืน
เพื่อนำ Audio Focus ไปใช้อย่างถูกต้อง คุณต้องทำสามขั้นตอนตามลำดับ: สร้างคำขอ ขอโฟกัสก่อนการเล่น และจัดการเหตุการณ์ใน callback การใช้ AudioFocusRequestCompat จาก AndroidX media ช่วยให้เข้ากันได้กับ Android ทุกเวอร์ชัน
val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val focusRequest = AudioFocusRequestCompat.Builder()
.setFocusGain(AudioManagerCompat.AUDIOFOCUS_GAIN)
.setOnAudioFocusChangeListener(focusChangeListener)
.build()
val result = AudioManagerCompat.requestAudioFocus(audioManager, focusRequest)
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
startPlayback()
}
คำขอโฟกัสต้องทำ ก่อน เริ่มเล่นทุกครั้งที่ผู้ใช้กด Play หากผลลัพธ์เป็น AUDIOFOCUS_REQUEST_GRANTED — เริ่มเล่น หากเป็น DENIED — แสดงข้อความให้ผู้ใช้ทราบหรือเลื่อนการเล่นออกไปจนกว่าจะได้รับโฟกัส
private val focusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
when (focusChange) {
AudioManager.AUDIOFOCUS_GAIN -> {
restoreVolume()
if (wasPlayingBeforeLoss) resumePlayback()
}
AudioManager.AUDIOFOCUS_LOSS -> {
pausePlayback()
wasPlayingBeforeLoss = false
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
pausePlayback()
wasPlayingBeforeLoss = true
}
AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
duckVolume()
}
}
}
ใน callback สิ่งสำคัญคือต้องแยกความแตกต่างระหว่าง AUDIOFOCUS_LOSS และ AUDIOFOCUS_LOSS_TRANSIENT ในกรณีแรก เครื่องเล่นไม่ควรเริ่มเล่นใหม่โดยอัตโนมัติ — ผู้ใช้เริ่มเสียงอื่นอย่างชัดเจน ในกรณีที่สอง สามารถเริ่มเล่นใหม่โดยอัตโนมัติเมื่อได้รับ AUDIOFOCUS_GAIN แฟล็ก wasPlayingBeforeLoss ช่วยจำว่าจำเป็นต้องกู้คืนการเล่นหรือไม่
private fun abandonAudioFocus() {
AudioManagerCompat.abandonAudioFocusRequest(audioManager, focusRequest)
}
การเรียก abandonAudioFocusRequest บอกระบบว่าแอปไม่ต้องการโฟกัสอีกต่อไป สิ่งสำคัญคือต้องเรียกมันเมื่อหยุดชั่วคราวและหยุดเครื่องเล่น หากไม่ปล่อยโฟกัส แอปอื่นที่ขอ AUDIOFOCUS_GAIN จะไม่ได้รับ LOSS และเสียงจะซ้อนทับกัน
การจัดการการสูญเสียโฟกัสอย่างถูกต้องเป็นข้อกำหนดสำคัญในการผ่านการตรวจสอบของ Google Play การจัดการที่ไม่ถูกต้องนำไปสู่รีวิวเชิงลบ: ผู้ใช้บ่นว่าเพลงยังคงเล่นต่อไประหว่างสายเรียกเข้าหรือทับการนำทาง
เมื่อได้รับ AUDIOFOCUS_LOSS เครื่องเล่นควรหยุดและไม่เริ่มเล่นใหม่จนกว่าผู้ใช้จะกด Play อย่างชัดเจน เมื่อ AUDIOFOCUS_LOSS_TRANSIENT (สายเรียกเข้า, การแจ้งเตือน) เครื่องเล่นหยุดชั่วคราวและเริ่มเล่นใหม่โดยอัตโนมัติเมื่อกู้คืนโฟกัส เมื่อ AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK เครื่องเล่นลดระดับเสียงชั่วคราวเหลือ 20–30% ในขณะที่เสียงภายนอกกำลังเล่น
ตามคู่มือนักพัฒนา Android (2026) ควรนำ duck ไปใช้โดยการคูณระดับเสียง AudioTrack ปัจจุบันด้วยปัจจัย 0.2–0.3 อย่าใช้ AudioManager.setStreamVolume — สิ่งนี้เปลี่ยนระดับเสียงของระบบและส่งผลต่อแอปอื่น Ducking ดำเนินการเฉพาะฝั่งเครื่องเล่นของตัวเองเท่านั้น
เมื่อมีสายเรียกเข้า ระบบจะขอ AUDIOFOCUS_GAIN_TRANSIENT โดยอัตโนมัติผ่านแอปโทรศัพท์ เครื่องเล่นได้รับ AUDIOFOCUS_LOSS_TRANSIENT และหยุดชั่วคราว หลังจากสายสิ้นสุดลงหรือหากผู้ใช้ปฏิเสธสาย โฟกัสจะกลับมา — เครื่องเล่นจะเริ่มเล่นใหม่โดยอัตโนมัติหากเป็นเครื่องเล่นเพลง
สำหรับแอปนำทาง (Google Maps) ใช้ AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK ระหว่างคำสั่งเสียง เครื่องเล่นจะลดเสียงลงเป็นเวลา 2–3 วินาที จากนั้นระดับเสียงจะถูกกู้คืน หากผู้ใช้กำลังฟังพอดแคสต์แทนเพลง ควรหยุดชั่วคราวแทนการ duck — ทุกวินาทีมีความสำคัญในพอดแคสต์
ในทางปฏิบัติ นักพัฒนาพบกับสถานการณ์มาตรฐานหลายอย่างที่ Audio Focus มีพฤติกรรมแตกต่างกัน มาดูกรณีทั่วไปและการตอบสนองที่ถูกต้องกัน
สิ่งสำคัญคือต้องนำแฟล็กที่จำได้ว่าเพลงกำลังเล่นอยู่ ก่อน การสูญเสียโฟกัสหรือไม่ หากผู้ใช้กดหยุดชั่วคราวเองแล้วมีสายเรียกเข้า — อย่าเริ่มเล่นใหม่ แฟล็กจะถูกรีเซ็ตเมื่อผู้ใช้หยุดชั่วคราวอย่างชัดเจนและถูกตั้งค่าเมื่อเริ่มเล่น
ตามการวิจัย UX ของ Google (2024) การเริ่มเล่นใหม่อัตโนมัติหลังสายเรียกเข้าช่วยเพิ่มความพึงพอใจของผู้ใช้ 22% แต่ถ้าเครื่องเล่นเริ่มเล่นใหม่หลังจากที่ผู้ใช้เริ่มดูวิดีโอแล้ว — สิ่งนี้ทำให้เกิดความรำคาญ แฟล็ก wasPlayingBeforeLoss ป้องกันการเริ่มเล่นที่ผิดพลาด
คำถามที่พบบ่อย
ใช่ ตั้งแต่ Android 12 เป็นต้นไป Google Play แนะนำให้นำ Audio Focus ไปใช้กับแอปทั้งหมดที่เล่นเสียง แอปประเภทเพลงและเสียงต้องนำไปใช้เพื่อเผยแพร่ การไม่สนใจอาจนำไปสู่การปฏิเสธการอัปเดต
เริ่มเครื่องเล่นของคุณ จากนั้นเปิดแอปเสียงอื่น (เช่น YouTube Music) เครื่องเล่นของคุณควรหยุดชั่วคราว จากนั้นปิด YouTube Music — เครื่องเล่นควรเริ่มเล่นใหม่โดยอัตโนมัติ สำหรับการทดสอบ duck ให้ใช้ Google Maps พร้อมคำสั่งเสียง
ระบบบอกว่า: “แอปอื่นจำเป็นต้องเล่นเสียงสั้น ๆ ชั่วคราว — ลดเสียง เครื่องเล่นของคุณ” สิ่งนี้เหมาะสมที่สุดสำหรับคำสั่งเสียงและการแจ้งเตือนสั้น ๆ ระดับเสียงจะถูกกู้คืนหลังจากเสียงภายนอกสิ้นสุดลงโดยไม่ต้องดำเนินการด้วยตนเอง
ในทางการ ใช่ — ระบบไม่บังคับ แต่ในทางปฏิบัติหมายถึง การซ้อนทับของเสียง ผู้ใช้จะได้ยินเพลงและสายเรียกเข้าพร้อมกัน ซึ่งนำไปสู่ประสบการณ์เชิงลบ Google แนะนำให้จัดการ AUDIOFOCUS_LOSS โดยการหยุดเครื่องเล่นเสมอ
บน iOS บทบาทที่เทียบเท่าดำเนินการโดย Audio Session ซึ่งจัดการผ่าน AVAudioSession กลไกคล้ายกัน: หมวดหมู่และตัวเลือกกำหนดพฤติกรรมระหว่างการซ้อนทับของเสียง อย่างไรก็ตาม API และกฎแตกต่างอย่างมีนัยสำคัญ — แต่ละเฟรมเวิร์กถูกนำไปใช้ในแบบของตัวเอง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ