gpt4 book ai didi

Android startBluetoothSco 不启动 sco 但 isBluetoothScoOn 返回 true

转载 作者:IT老高 更新时间:2023-10-28 23:25:34 26 4
gpt4 key购买 nike

我创建了一个带有示例项目的 GitHub 存储库,该项目显示了我在这里询问的以下问题:
https://github.com/paulpv/audio-loopback/tree/simplified/src/com/twistpair/wave/experimental/loopback
(请坚持使用“简化”分支并忽略“主”分支)

两个主要文件是:

  • https://github.com/paulpv/audio-loopback/blob/simplified/src/com/twistpair/wave/experimental/loopback/MainActivity.java
  • https://github.com/paulpv/audio-loopback/blob/simplified/src/com/twistpair/wave/experimental/loopback/AudioStateManager.java

  • 免责声明:我目前只使用一个运行 CyanogenMod 10 Jelly Bean 的三星 Epic SPH-D700 来编码和测试它。我还没有在其他设备上尝试过这个,但也许这可能有助于阻止我把头发拉出来发疯。

    我一直在努力让 Android 蓝牙 SCO 升级到 可靠 开始和停止以及捕获/播放音频 !
    一旦我可以让手机进入 SCO 模式,通过 AudioRecord 和 AudioTrack(分别)捕获和播放就可以正常工作了。
    我遇到的问题是我无法可靠地让手机进入 SCO 模式!

    “互联网”上使用 startBluetoothSco() 和 setBluetoothScoOn(true) 的示例看起来都很简单直接,但是当我在我的设备上使用它们时,它们几乎无法可靠地工作。
    我创建了自己的测试应用程序,它除了启动和停止 SCO 什么都不做,我什至无法让它可靠地工作!

    我的代码监听 BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED EXTRA_STATE==CONNECTED.我可以可靠地检测到任何耳机何时连接或断开连接。

    当检测到连接时,我的处理程序会立即调用 startBluetoothSco()。
    A 可以发誓,至少一旦这被踢了 SCO_AUDIO_STATE至 C O NNECTED,但在 99% 的情况下,它只会导致从 DISCONNECTED->CONNECTING->DISCONNECTED 的转换.

    这是我的 GitHub 示例应用程序中带注释的日志输出:
    10-03 17:00:13.970: I/dalvikvm(29487): Debugger is active
    10-03 17:00:14.158: I/System.out(29487): Debugger has connected
    10-03 17:00:15.779: I/System.out(29487): waiting for debugger to settle...
    10-03 17:00:15.978: I/System.out(29487): debugger has settled (1325)

    我的应用程序在关闭 Jawbone 耳机的情况下启动并更新 UI...
    10-03 17:00:16.568: D/MainActivity(29487): updateScreen()...
    10-03 17:00:16.572: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false

    ...用户界面更新完成
    粘性广播告诉我当前的 SCO_AUDIO_STATE...
    10-03 17:00:16.689: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.media.ACTION_SCO_AUDIO_STATE_UPDATED flg=0x10 (has extras) }
    10-03 17:00:16.689: D/AudioStateManager(29487): extras={"android.media.extra.SCO_AUDIO_PREVIOUS_STATE"=2, "android.media.extra.SCO_AUDIO_STATE"=0}
    10-03 17:00:16.689: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED
    10-03 17:00:16.693: D/AudioStateManager(29487): ==> scoAudioStatePrevious=SCO_AUDIO_STATE_CONNECTING(2)
    10-03 17:00:16.693: D/AudioStateManager(29487): ==> scoAudioState=SCO_AUDIO_STATE_DISCONNECTED(0)
    10-03 17:00:16.693: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED: SCO_AUDIO_STATE_DISCONNECTED

    ...当前 SCO_AUDIO_STATE == DISCONNECTED;预期,因为我的耳机已关闭。
    我的 SCO Disconnected 事件监听器被调用并更新带有两个 sendMessages 的 UI...
    10-03 17:00:16.693: I/MainActivity(29487): onAudioManagerScoAudioDisconnected()
    10-03 17:00:16.755: D/libEGL(29487): loaded /vendor/lib/egl/libEGL_POWERVR_SGX540_120.so
    10-03 17:00:16.787: D/libEGL(29487): loaded /vendor/lib/egl/libGLESv1_CM_POWERVR_SGX540_120.so
    10-03 17:00:16.791: D/libEGL(29487): loaded /vendor/lib/egl/libGLESv2_POWERVR_SGX540_120.so
    10-03 17:00:16.888: D/OpenGLRenderer(29487): Enabling debug mode 0
    10-03 17:00:16.912: D/MainActivity(29487): MSG_UPDATE_BLUETOOTH_INDICATION
    10-03 17:00:16.912: D/MainActivity(29487): updateScreen()...
    10-03 17:00:16.912: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false
    10-03 17:00:16.927: D/MainActivity(29487): MSG_UPDATE_AUDIO_OUTPUT_STREAM_TYPE
    10-03 17:00:16.927: D/MainActivity(29487): updateScreen()...
    10-03 17:00:16.931: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false

    ...用户界面更新完成

    大约 20 秒后,我打开了 Jawbone 耳机...
    10-03 17:00:37.572: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED flg=0x10 (has extras) }
    10-03 17:00:37.583: D/AudioStateManager(29487): extras={"android.bluetooth.device.extra.DEVICE"=00:21:3C:00:3E:02, "android.bluetooth.profile.extra.PREVIOUS_STATE"=0, "android.bluetooth.profile.extra.STATE"=1}
    10-03 17:00:37.587: D/AudioStateManager(29487): mReceiver: BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED
    10-03 17:00:37.587: D/AudioStateManager(29487): ==> bluetoothDevice=00:21:3C:00:3E:02
    10-03 17:00:37.587: D/AudioStateManager(29487): ==> bluetoothHeadsetStatePrevious=STATE_DISCONNECTED(0)
    10-03 17:00:37.587: D/AudioStateManager(29487): ==> bluetoothHeadsetState=STATE_CONNECTING(1)
    10-03 17:00:37.619: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED flg=0x10 (has extras) }
    10-03 17:00:37.623: D/AudioStateManager(29487): extras={"android.bluetooth.device.extra.DEVICE"=00:21:3C:00:3E:02, "android.bluetooth.profile.extra.PREVIOUS_STATE"=1, "android.bluetooth.profile.extra.STATE"=2}
    10-03 17:00:37.623: D/AudioStateManager(29487): mReceiver: BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED
    10-03 17:00:37.623: D/AudioStateManager(29487): ==> bluetoothDevice=00:21:3C:00:3E:02
    10-03 17:00:37.626: D/AudioStateManager(29487): ==> bluetoothHeadsetStatePrevious=STATE_CONNECTING(1)
    10-03 17:00:37.626: D/AudioStateManager(29487): ==> bluetoothHeadsetState=STATE_CONNECTED(2)

    颚骨连接;我的事件监听器被称为...
    10-03 17:00:37.626: I/MainActivity(29487): onBluetoothHeadsetConnected()

    ...看到我们可以SCO ...
    10-03 17:00:37.626: D/AudioStateManager(29487): mAudioManager.isBluetoothScoAvailableOffCall()=true

    ...并自动调用 startBluetoothSco()
    这就是问题所在!为什么这个对 startBluetoothSco 的调用不会导致 SCO_AUDIO_STATE == CONNECTED?!?!
    10-03 17:00:37.626: D/AudioStateManager(29487): startBluetoothSco()
    10-03 17:00:37.626: I/AudioStateManager(29487): mAudioManager.startBluetoothSco();

    我的事件监听器使用 sendMessage 完成以使用当前 BT 状态更新 UI...
    10-03 17:00:37.646: D/MainActivity(29487): MSG_UPDATE_BLUETOOTH_INDICATION
    10-03 17:00:37.650: D/MainActivity(29487): updateScreen()...
    10-03 17:00:37.650: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false

    ...用户界面更新完成
    startBluetoothSco 的第一个结果是......
    10-03 17:00:37.681: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.media.ACTION_SCO_AUDIO_STATE_UPDATED flg=0x10 (has extras) }
    10-03 17:00:37.681: D/AudioStateManager(29487): extras={"android.media.extra.SCO_AUDIO_STATE"=2, "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"=0}
    10-03 17:00:37.681: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED
    10-03 17:00:37.685: D/AudioStateManager(29487): ==> scoAudioStatePrevious=SCO_AUDIO_STATE_DISCONNECTED(0)
    10-03 17:00:37.685: D/AudioStateManager(29487): ==> scoAudioState=SCO_AUDIO_STATE_CONNECTING(2)

    ...从断开连接到连接
    startBluetoothSco 的第二个结果是......
    10-03 17:00:37.759: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.media.ACTION_SCO_AUDIO_STATE_UPDATED flg=0x10 (has extras) }
    10-03 17:00:37.763: D/AudioStateManager(29487): extras={"android.media.extra.SCO_AUDIO_STATE"=0, "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"=2}
    10-03 17:00:37.763: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED
    10-03 17:00:37.763: D/AudioStateManager(29487): ==> scoAudioStatePrevious=SCO_AUDIO_STATE_CONNECTING(2)
    10-03 17:00:37.763: D/AudioStateManager(29487): ==> scoAudioState=SCO_AUDIO_STATE_DISCONNECTED(0)
    10-03 17:00:37.763: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED: SCO_AUDIO_STATE_DISCONNECTED

    ...从连接移至 已断开
    我本来希望 SCO 从 CONNECTING 转到 已连接 !
    我的事件监听器被调用并使用两个 sendMessages 更新 UI...
    10-03 17:00:37.763: I/MainActivity(29487): onAudioManagerScoAudioDisconnected()
    10-03 17:00:37.767: D/MainActivity(29487): MSG_UPDATE_BLUETOOTH_INDICATION
    10-03 17:00:37.767: D/MainActivity(29487): updateScreen()...
    10-03 17:00:37.767: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false
    10-03 17:00:37.783: D/MainActivity(29487): MSG_UPDATE_AUDIO_OUTPUT_STREAM_TYPE
    10-03 17:00:37.783: D/MainActivity(29487): updateScreen()...
    10-03 17:00:37.783: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false

    ...用户界面更新完成

    我等待 SCO 连接约 20 秒,但它永远不会出现。
    我按下我的应用程序的“startBluetoothSco”按钮。
    请注意,这与在 17:00:37.626 调用 startBluetoothSco() 的结果完全相同
    10-03 17:01:01.689: D/AudioStateManager(29487): startBluetoothSco()
    10-03 17:01:01.689: I/AudioStateManager(29487): mAudioManager.startBluetoothSco();

    startBluetoothSco 的第一个结果是......
    10-03 17:01:01.708: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.media.ACTION_SCO_AUDIO_STATE_UPDATED flg=0x10 (has extras) }
    10-03 17:01:01.712: D/AudioStateManager(29487): extras={"android.media.extra.SCO_AUDIO_STATE"=2, "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"=0}
    10-03 17:01:01.712: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED
    10-03 17:01:01.712: D/AudioStateManager(29487): ==> scoAudioStatePrevious=SCO_AUDIO_STATE_DISCONNECTED(0)
    10-03 17:01:01.712: D/AudioStateManager(29487): ==> scoAudioState=SCO_AUDIO_STATE_CONNECTING(2)

    ...从断开连接到连接
    这里是与 startBluetoothSco() 在 17:00:37.626 的自动调用不同的地方
    我们得到一个 蓝牙耳机。ACTION_AUDIO_STATE_CHANGED 事件...
    10-03 17:01:01.716: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED flg=0x10 (has extras) }
    10-03 17:01:01.720: D/AudioStateManager(29487): extras={"android.bluetooth.device.extra.DEVICE"=00:21:3C:00:3E:02, "android.bluetooth.profile.extra.PREVIOUS_STATE"=10, "android.bluetooth.profile.extra.STATE"=11}
    10-03 17:01:01.720: D/AudioStateManager(29487): mReceiver: BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED
    10-03 17:01:01.720: D/AudioStateManager(29487): ==> bluetoothDevice=00:21:3C:00:3E:02
    10-03 17:01:01.720: D/AudioStateManager(29487): ==> bluetoothHeadsetAudioStatePrevious=STATE_AUDIO_DISCONNECTED(10)
    10-03 17:01:01.720: D/AudioStateManager(29487): ==> bluetoothHeadsetAudioState=STATE_AUDIO_CONNECTING(11)

    ...从断开连接到连接
    我们得到另一个 BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED 事件...
    10-03 17:01:02.572: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED flg=0x10 (has extras) }
    10-03 17:01:02.576: D/AudioStateManager(29487): extras={"android.bluetooth.device.extra.DEVICE"=00:21:3C:00:3E:02, "android.bluetooth.profile.extra.PREVIOUS_STATE"=11, "android.bluetooth.profile.extra.STATE"=12}
    10-03 17:01:02.576: D/AudioStateManager(29487): mReceiver: BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED
    10-03 17:01:02.576: D/AudioStateManager(29487): ==> bluetoothDevice=00:21:3C:00:3E:02
    10-03 17:01:02.576: D/AudioStateManager(29487): ==> bluetoothHeadsetAudioStatePrevious=STATE_AUDIO_CONNECTING(11)
    10-03 17:01:02.580: D/AudioStateManager(29487): ==> bluetoothHeadsetAudioState=STATE_AUDIO_CONNECTED(12)

    ...从连接移动到连接
    事件通过一个 sendMessage 更新 UI
    10-03 17:01:02.580: I/MainActivity(29487): onBluetoothHeadsetAudioConnected()
    10-03 17:01:02.580: D/MainActivity(29487): MSG_UPDATE_BLUETOOTH_INDICATION
    10-03 17:01:02.580: D/MainActivity(29487): updateScreen()...
    10-03 17:01:02.583: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true

    ... UI 更新完成(老实说,我不确定第二次调用 isBluetoothScoOn 是什么)
    10-03 17:01:02.603: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true

    startBluetoothSco 的第二个结果是......
    10-03 17:01:02.603: D/AudioStateManager(29487): onReceive: intent=Intent { act=android.media.ACTION_SCO_AUDIO_STATE_UPDATED flg=0x10 (has extras) }
    10-03 17:01:02.607: D/AudioStateManager(29487): extras={"android.media.extra.SCO_AUDIO_STATE"=1, "android.media.extra.SCO_AUDIO_PREVIOUS_STATE"=2}
    10-03 17:01:02.607: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED
    10-03 17:01:02.607: D/AudioStateManager(29487): ==> scoAudioStatePrevious=SCO_AUDIO_STATE_CONNECTING(2)
    10-03 17:01:02.607: D/AudioStateManager(29487): ==> scoAudioState=.SCO_AUDIO_STATE_CONNECTED(1)
    10-03 17:01:02.607: D/AudioStateManager(29487): android.media.ACTION_SCO_AUDIO_STATE_UPDATED: SCO_AUDIO_STATE_CONNECTED

    ...从连接移动到连接

    最后!
    我的事件监听器被调用并使用两个 sendMessages 更新 UI...
    10-03 17:01:02.611: I/MainActivity(29487): onAudioManagerScoAudioConnected()
    10-03 17:01:02.630: D/MainActivity(29487): MSG_UPDATE_BLUETOOTH_INDICATION
    10-03 17:01:02.630: D/MainActivity(29487): updateScreen()...
    10-03 17:01:02.634: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true
    10-03 17:01:02.650: D/MainActivity(29487): MSG_UPDATE_AUDIO_OUTPUT_STREAM_TYPE
    10-03 17:01:02.650: D/MainActivity(29487): updateScreen()...
    10-03 17:01:02.650: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true

    ...用户界面更新完成

    当我在一段时间后“手动”启动 SCO 时,一切(这次)都可以工作,但如果我在连接耳机后立即自动启动 SCO 则不行。

    更糟糕的是,当事情没有按预期工作时,我在 SCO 状态中看到了奇怪的行为:
  • 将 startBluetoothSco() 延迟 3-5 秒似乎没什么区别。我还没有尝试将它延迟超过 5 秒。等待超过 5 秒让音频开始流入您的 BT 耳机是荒谬的。
  • 有时调用 isBluetoothScoOn() 会返回 true,即使自从上次 DISCONNECTED 状态说该状态更改为 CONNECTED 以来,我从未收到过广播事件。
  • 有时从用户界面“手动”调用 startBluetoothSco() 什么也不做,就好像 SCO 已经打开一样,但自从上次 DISCONNECTED 状态说状态更改为 CONNECTED 以来,我从未收到任何广播事件。
  • 尝试打开 AudioTrack 或 AudioRecord 结果没有声音(当 SCO 没有行为不端时,同样的代码可以正常工作。即:问题在于 SCO 状态,而不是 AudioTrack/AudioRecord 调用)。
  • 调用 stopBluetoothSco() 不会导致任何事件报告状态为 DISCONNECTED。
  • setBluetoothScoOn(false/true) 没有区别。老实说,我不明白看似多余的“startBluetoothSco()/stopBluetoothSco()”和“setBluetoothScoOn(boolean)”的区别。当一切正常时,我调用 startBluetoothSco() 导致 isBluetoothScoOn() 返回 true,这让我认为我不需要调用 setBluetoothScoOn(true)。
  • 重新启动手机没有任何区别。
  • 重新启动耳机没有任何区别。
  • 更换为其他耳机没有任何区别。
  • 有时耳机会失去配对,必须重新配对。

  • 鉴于谷歌/Android 在蓝牙支持方面的记录,我对此并不感到惊讶。

    有人可以让我摆脱痛苦并明确解释如何在Android中可靠地启动和停止蓝牙SCO吗?

    PS:是否有官方 channel 可以将此类问题上报 [w/Google?三星?]?或者,StackOverflow 是我找到实际答案的最佳机会吗?

    最佳答案

    Android 文档中缺少许多内容,但是,如果您在音频路由期间每次调用 startBluetoothSco() 和 stopBluetoothSco(),那么正确路由音频应该没有问题。
    即使我已经看到当连接长时间保持空闲并且我们启动 StartBluetoothSco() 时,我们会直接断开连接。
    为了解决这个问题,我写了一个解决方法,在这里:https://github.com/kodered/Bluetooth-Refresh-Logic

    希望这可以帮助。

    关于Android startBluetoothSco 不启动 sco 但 isBluetoothScoOn 返回 true,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12737446/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com