【问题标题】:Android : Wear Watches reported as connected Bluetooth headsets?Android:Wear Watches 报告为连接的蓝牙耳机?
【发布时间】:2022-11-11 15:14:24
【问题描述】:

我的倒计时应用程序使用文本转语音来提供音频倒计时。

当应用程序检测到蓝牙扬声器时,音频会发送到该扬声器。

三星 Watch 4 和 TicWatch Pro 3 等可穿戴设备被报告为耳机问题!

例如我原来的 onCreate() 包括:

// Check if a speaker is connected 
if (bluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED) 
    sendSpeechToSpeaker()
else 
    sendSpeechToPhone()

问题 1上面是否有一个简单的修复方法,它只会检测连接的耳机?

我的解决方法包括单独检查每个连接的蓝牙设备并忽略那些不是耳机的设备

问题2有人可以提出比我的解决方法更简单的方法吗?

解决方法

在初始化期间,检查每个 CONNECTED 蓝牙设备,如果它们实际上是耳机,则重新路由音频

检查每个 CONNECTED 设备的 btServiceListener

val btServiceListener: ServiceListener = object : ServiceListener {
    // used to scan all CONNECTED Bluetooth devices looking for external speakers ...
    override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
        if (profile == BluetoothProfile.HEADSET) {
            val connectionStates = intArrayOf(BluetoothProfile.STATE_CONNECTED) 
            // get all connected headsets
            val connectedHeadsetList = proxy.getDevicesMatchingConnectionStates(connectionStates)
            for (connectedHeadset in connectedHeadsetList) {
                // check each headset and check if it is ACTUALLY a headset
                val majorMask = BluetoothClass.Device.Major.UNCATEGORIZED // actually want to use BITMASK but some Fwit declared it private !
                val isHeadset = (connectedHeadset.bluetoothClass?.deviceClass?.and(majorMask) == BluetoothClass.Device.Major.AUDIO_VIDEO)
                if (isHeadset) 
                    sendSpeechToSpeaker()
                }
            }
            bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, proxy) // here we are finished with the proxy so clear
        }
        override fun onServiceDisconnected(profile: Int) {}
    }

上面的监听器在 onCreate() 中被调用

// search the list of connected bluetooth headsets
bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
bluetoothAdapter = bluetoothManager.adapter
bluetoothAdapter.getProfileProxy(this, btServiceListener, BluetoothProfile.HEADSET);

Listener 使用 Major Mask 工作 HEADSETS 的代码是 (0x0400) 三星 Galaxy 手表可穿戴 (0x0700) TicWatch Pro 3 GPS 未分类 (0x1F00)

为简单起见,我没有在 BTListener 中显示相同的代码,以确保如果手表断开连接,它不会将音频从扬声器路由出去!

【问题讨论】:

    标签: android bluetooth


    【解决方案1】:

    可以通过直接检查音频属性而不是解析每个连接的蓝牙设备来避免上述问题

    private fun routeTTSAudioOutput() {
        // on start and when changes are detected ensure audio is being routed correctly
        val bluetoothA2DPConnected = audioOutputAvailable(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP)
        if (bluetoothA2DPConnected) {
            if (!bluetoothSCOTurnedOn) audioManager.startBluetoothSco()
            audioManager.mode = AudioManager.MODE_IN_CALL
        } else {
            if (bluetoothSCOTurnedOn) audioManager.stopBluetoothSco()
            audioManager.mode = AudioManager.MODE_NORMAL
        }
        audioManager.isSpeakerphoneOn = !bluetoothA2DPConnected
        bluetoothSCOTurnedOn = bluetoothA2DPConnected
        bundleTTS = Bundle()
        bundleTTS.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, audioManager.mode)
        this.runOnUiThread { bluetoothConnectedImageView.visibility = if (bluetoothA2DPConnected) ImageView.VISIBLE else ImageView.INVISIBLE }
    }
    

    音频回调使用上述函数将文本路由到语音

    private val audioDeviceCallback : AudioDeviceCallback = object : AudioDeviceCallback() {
        override fun onAudioDevicesAdded(addedDevices: Array<out AudioDeviceInfo>?) {
            super.onAudioDevicesAdded(addedDevices)
            routeTTSAudioOutput()
        }
        override fun onAudioDevicesRemoved(removedDevices: Array<out AudioDeviceInfo>?) {
            super.onAudioDevicesRemoved(removedDevices)
            routeTTSAudioOutput()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多