เปิดเสียงบนอุปกรณ์ที่สวมใส่ได้

คู่มือนี้อธิบายวิธีใช้ Android API ที่คุ้นเคยเพื่อเล่นเสียงในแอป Wear OS

ตรวจหาอุปกรณ์เสียง

แอป Wear OS ต้องตรวจหาก่อนว่าอุปกรณ์ที่สวมใส่ได้มีเอาต์พุตเสียงที่เหมาะสมหรือไม่ โดยทั่วไปแล้วอุปกรณ์สวมใส่จะมีเอาต์พุตเสียงอย่างน้อย 1 รายการต่อไปนี้

  • AudioDeviceInfo.TYPE_BUILTIN_SPEAKER: ในอุปกรณ์ที่มีลำโพงในตัว
  • AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: เมื่อจับคู่และเชื่อมต่อชุดหูฟังบลูทูธ
  • AudioDeviceInfo.TYPE_BLE_BROADCAST: เมื่อจับคู่และเชื่อมต่ออุปกรณ์กลุ่มการออกอากาศบลูทูธพลังงานต่ำ (BLE)
  • AudioDeviceInfo.TYPE_BLE_HEADSET: เมื่อจับคู่และเชื่อมต่อชุดหูฟัง BLE
  • AudioDeviceInfo.TYPE_BLE_SPEAKER: เมื่อจับคู่และเชื่อมต่อลำโพง BLE

ตัวอย่างต่อไปนี้ใช้เมธอด getDevices() กับค่า FEATURE_AUDIO_OUTPUT เพื่อตรวจสอบว่ามีเอาต์พุตเสียงประเภทใดบ้าง

private val audioManager: AudioManager by lazy {
    getSystemService(AUDIO_SERVICE) as AudioManager
}

fun audioOutputAvailable(type: Int): Boolean {
    if (!packageManager.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
        return false
    }
    return audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS).any { it.type == type }
}

จากนั้นคุณสามารถใช้เมธอดนี้เพื่อตรวจสอบว่ามีเอาต์พุตเสียงประเภทใดบ้าง

val hasSpeaker = audioOutputAvailable(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER)
val hasBluetoothHeadset = audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)
val hasBLEBroadcast = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST)
val hasBLEHeadset = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET)
val hasBLESpeaker = audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER)

เพื่อมอบประสบการณ์ของผู้ใช้ที่ดีที่สุด ให้เล่นสื่อเมื่อหูฟังหรือลำโพงบลูทูธเชื่อมต่อกับนาฬิกาเท่านั้น

เลือกอุปกรณ์หลักสำหรับเอาต์พุตเสียง

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

อนุญาตให้ผู้ใช้เลือกอุปกรณ์เอาต์พุตสื่อ

ตั้งแต่ Wear OS 5 เป็นต้นไป ระบบจะมี UI ที่ช่วยให้ผู้ใช้เลือกอุปกรณ์ที่จะเล่นสื่อและแสดงข้อมูลเกี่ยวกับเนื้อหาสื่อที่กำลังเล่น

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

เมธอด launchOutputSelection() ซึ่งเป็นส่วนหนึ่งของไลบรารี ใน GitHub แสดงวิธีอนุญาตให้ผู้ใช้เลือกอุปกรณ์เอาต์พุตสื่อ

ชุดหูฟังบลูทูธ

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

val audioDeviceCallback =
    object : AudioDeviceCallback() {
        override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
            super.onAudioDevicesAdded(addedDevices)
            if (audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP) ||
                audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST) ||
                audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET) ||
                audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER)
            ) {
                // A Bluetooth or BLE device is connected and available for playback.
            }
        }
        override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
            super.onAudioDevicesRemoved(removedDevices)
            if (!(audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)) &&
                !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_BROADCAST)) &&
                !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_HEADSET)) &&
                !(audioOutputAvailable(AudioDeviceInfo.TYPE_BLE_SPEAKER))
            ) {
                // No Bluetooth or BLE devices are connected anymore.
            }
        }
    }

audioManager.registerAudioDeviceCallback(audioDeviceCallback, /*handler=*/ null)

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

fun Context.launchBluetoothSettings(closeOnConnect: Boolean = true) {
    val intent = with(Intent(Settings.ACTION_BLUETOOTH_SETTINGS)) {
        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
        putExtra("EXTRA_CONNECTION_ONLY", true)
        if (closeOnConnect) {
            putExtra("EXTRA_CLOSE_ON_CONNECT", true)
        }
        putExtra("android.bluetooth.devicepicker.extra.FILTER_TYPE", FILTER_TYPE_AUDIO)
    }
    startActivity(intent)
}

internal const val FILTER_TYPE_AUDIO = 1

ลำโพงในตัว

อุปกรณ์ Wear OS ส่วนใหญ่มีลำโพงในตัว หากแอปมีกรณีการใช้งานที่ไม่ใช่สื่อที่ใช้เสียง ให้พิจารณาใช้ลำโพงเพื่อเพิ่มมิติใหม่ๆ ในการมีส่วนร่วม เช่น อุปกรณ์ Wear OS ที่มีลำโพงอาจส่งเสียงเตือนของนาฬิกาหรือตัวจับเวลาพร้อมการแจ้งเตือนด้วยเสียง และแอปฟิตเนสอาจใช้ลำโพงเพื่อแสดงคำแนะนำการออกกำลังกาย

ดูรายละเอียดได้ที่ WearSpeakerSample

เล่นเสียง

หลังจากตรวจหาและเลือกเอาต์พุตเสียงที่เหมาะสมแล้ว การเล่นเสียงใน Wear OS จะเหมือนกับการเล่นเสียงในอุปกรณ์เคลื่อนที่หรืออุปกรณ์อื่นๆ ดูข้อมูลเพิ่มเติมได้ที่ ภาพรวมของ MediaPlayer ใช้ ExoPlayer เพื่อให้เข้าถึงฟีเจอร์ขั้นสูงได้ง่ายขึ้น เช่น การสตรีมและ การดาวน์โหลดสื่อ ทำตามแนวทางปฏิบัติแนะนำสำหรับแอปเสียง เช่น เช่น การจัดการโฟกัสเสียง

ป้องกันการเล่นสื่อโดยไม่ตั้งใจผ่านลำโพงในตัว

แอปสื่อสามารถทำตามคำแนะนำนี้เพื่อป้องกันไม่ให้แอปเล่นสื่อในลำโพงในตัวของนาฬิกาโดยไม่ตั้งใจ คำแนะนำจะแตกต่างกันไปตามเพลเยอร์ที่แอปใช้

ExoPlayer

หากแอปใช้ ExoPlayer ให้ทำดังนี้

  1. เรียกใช้ setSuppressPlaybackOnUnsuitableOutput(true) เมธอด ขณะ สร้างอินสแตนซ์ ExoPlayer

val exoPlayer = ExoPlayer.Builder(context)
    .setAudioAttributes(AudioAttributes.DEFAULT, true)
    .setSuppressPlaybackOnUnsuitableOutput(true)
    .build()

  1. ตอบสนองต่อเหตุการณ์การระงับการเล่นโดยลงทะเบียน WearUnsuitableOutputPlaybackSuppressionResolverListener Listener เป็น Listener ของอินสแตนซ์ ExoPlayer

exoPlayer.addListener(WearUnsuitableOutputPlaybackSuppressionResolverListener(context))

ชุดเครื่องมือสื่อ Horologist

ชุดเครื่องมือสื่อ Horologist มีตรรกะเพื่อป้องกัน การเล่นสื่อโดยไม่ตั้งใจในลำโพงในตัวของนาฬิกาอยู่แล้ว

เครื่องเล่นสื่ออื่นๆ