Android startBluetoothSco no comienza sco pero isBluetoothScoOn devuelve true
He creado un repo GitHub con un proyecto de muestra que muestra el siguiente problema que estoy preguntando aquí:
Https://github.com/paulpv/audio-loopback/tree/simplified/src/com/twistpair/wave/experimental/loopback
(Póngase por favor con la rama "simplificada" y no tenga en cuenta la rama "principal"
Los dos archivos principales son:
- Servidor Android Bluetooth de Baja Energía
- ¿Puede un dispositivo Android actuar como iBeacon?
- El dispositivo Android BLE se desconecta después de poco tiempo, el código de error 8
- Android - startActivityForResult fuera de una actividad?
- Android: socket bluetooth se niegan a conectarse correctamente
- 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
Exención de responsabilidad: Actualmente sólo estoy usando un solo Samsung Epic SPH-D700 ejecutando CyanogenMod 10 Jelly Bean para codificar y probar esto con. No he probado esto en otros dispositivos, pero quizás eso podría ayudar a pararme de tirar de mi pelo hacia fuera y de ir loco.
He estado luchando para conseguir Android SCO Bluetooth para iniciar y detener de forma fiable y capturar / reproducir audio POR MESES !
Una vez que consiga el teléfono en el modo SCO, captura y reproducción a través de AudioRecord y AudioTrack (respectivamente) funciona bien según lo documentado.
El problema que estoy teniendo es que no puedo confiar el teléfono en el modo SCO!
Los ejemplos de "Internet" para usar startBluetoothSco () y setBluetoothScoOn (true) parecen sencillos y sencillos, pero cuando los uso en mi dispositivo casi nunca funcionan de manera confiable.
He creado mi propia aplicación de prueba que no hace nada más que iniciar y detener SCO, y no puedo ni siquiera conseguir esto para trabajar confiablemente!
Mi código escucha un BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED EXTRA_STATE==CONNECTED.
Puedo detectar de forma fiable cualquier auricular conectado o desconectado.
Al detectar una conexión mi manejador llama inmediatamente a startBluetoothSco ().
A podría jurar que al menos una vez esto ha pateado SCO_AUDIO_STATE
a C O
NNECTED, pero el 99% del tiempo sólo resulta en una transición de DISCONNECTED->CONNECTING->DISCONNECTED
.
Esta es mi salida de registro anotada de mi aplicación de ejemplo de 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)
Mi aplicación se inicia con el auricular Jawbone desactivado y actualiza la interfaz de usuario …
10-03 17:00:16.568: D/MainActivity(29487): updateScreen()... 10-03 17:00:16.572: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false
… actualización de la interfaz de usuario hecha
Difusión pegajosa que me dice el SCO_AUDIO_STATE actual …
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
… actual SCO_AUDIO_STATE == DESCONECTADO; Esperado, ya que mi auricular está apagado.
Mi detector de eventos SCO desconectado se llama y actualiza la interfaz de usuario con dos sendMessages …
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
… actualización de la interfaz de usuario hecha
Después de ~ 20 segundos enciendo mi auricular 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)
Jawbone conectado; Mi detector de eventos se llama …
10-03 17:00:37.626: I/MainActivity(29487): onBluetoothHeadsetConnected()
… ve que podemos SCO …
10-03 17:00:37.626: D/AudioStateManager(29487): mAudioManager.isBluetoothScoAvailableOffCall()=true
… y las llamadas automáticas startBluetoothSco ()
¡AQUÍ ESTÁ DÓNDE ESTÁ EL PROBLEMA! ¿Por qué esta llamada a startBluetoothSco no resulta en 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();
Mi oyente de evento termina w / a sendMessage para actualizar la interfaz de usuario con el estado BT actual …
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
… actualización de la interfaz de usuario hecha
El primer resultado de startBluetoothSco viene en …
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)
… pasó de DESCONECTADO a CONEXIÓN
El segundo resultado de startBluetoothSco viene en …
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
… pasó de CONECTAR a DESCONECTADO
¡Yo habría esperado que SCO pasara de CONECTAR a CONECTADO !
Mi detector de eventos se llama y actualiza la interfaz de usuario con dos sendMessages …
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
… actualización de la interfaz de usuario hecha
Espero ~ 20 segundos para SCO conectado, pero nunca llega.
Presiono el botón "startBluetoothSco" de mi aplicación.
TENGA EN CUENTA QUE ESTO RESULTA EN LA LLAMADA EXACTA DE INICIO a startBluetoothSco () EN 17: 00: 37.626
10-03 17:01:01.689: D/AudioStateManager(29487): startBluetoothSco() 10-03 17:01:01.689: I/AudioStateManager(29487): mAudioManager.startBluetoothSco();
El primer resultado de startBluetoothSco viene en …
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)
… pasó de DESCONECTADO a CONEXIÓN
Aquí es donde las cosas difieren de la auto-llamada de startBluetoothSco () en 17: 00: 37.626
Obtenemos un evento BluetoothHeadset.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)
… pasó de DESCONECTADO a CONEXIÓN
Obtenemos otro evento 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)
… pasó de CONECTAR a CONECTADO
El evento actualiza la UI w / one sendMessage
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
… actualización de la interfaz de usuario hecho (Para ser honesto, no estoy seguro de lo que está llamando isBluetoothScoOn una segunda vez)
10-03 17:01:02.603: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true
El segundo resultado de startBluetoothSco viene en …
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
… pasó de CONECTAR a CONECTADO
¡FINALMENTE!
Mi detector de eventos se llama y actualiza la interfaz de usuario con dos sendMessages …
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
… actualización de la interfaz de usuario hecha
Todo (esta vez) funciona cuando inicio "manualmente" SCO después de algún tiempo, pero no si comienzo automáticamente SCO inmediatamente después de conectar un auricular.
Para empeorar las cosas, cuando las cosas no funcionan como esperaba, veo un comportamiento extraño en los estados de la SCO:
- Retrasar el startBluetoothSco () para unos 3-5 segundos resonable parece no hacer ninguna diferencia. No he intentado retrasarlo más de 5 segundos. Esperar más de 5 segundos para que el audio comience a fluir a su auricular BT es ridículo.
- A veces llamar a isBluetoothScoOn () devuelve true, incluso cuando nunca he recibido un evento de difusión desde el último estado DISCONNECTED diciendo que el estado cambió a CONNECTED.
- A veces "manualmente" llamando a startBluetoothSco () de la interfaz de usuario no hace nada, como si SCO ya está encendido, pero nunca recibí ningún evento de difusión desde el último estado DESCONECTADO diciendo que el estado cambiado a CONECTADO.
- Intentar abrir AudioTrack o AudioRecord no produce sonido (este mismo código funciona bien cuando SCO no se está portando mal, es decir: el problema es el estado SCO, no las llamadas AudioTrack / AudioRecord).
- Llamar stopBluetoothSco () no produce ningún estado de informe de evento DISCONNECTED.
- SetBluetoothScoOn (false / true) no hace ninguna diferencia. Para ser honesto no entiendo la diferencia en el aparentemente redundante "startBluetoothSco () / stopBluetoothSco ()" y "setBluetoothScoOn (boolean)". Cuando las cosas funcionan, mi llamada startBluetoothSco () resulta en isBluetoothScoOn () devolviendo true haciéndome pensar que no necesito llamar a setBluetoothScoOn (true).
- Reiniciar el teléfono no hace ninguna diferencia.
- Reiniciar el auricular no hace ninguna diferencia.
- Cambiar a otro auricular no hace ninguna diferencia.
- A veces, el auricular pierde su emparejamiento y tiene que volver a emparejarse.
Teniendo en cuenta la trayectoria de Google / Android en el soporte Bluetooth, muy poco de esto me sorprende.
¿Puede alguien por favor me puso fuera de mi miseria y sin duda explicar cómo de forma fiable iniciar y detener bluetooth SCO en Android?
PS: ¿Existe un canal oficial para escalar temas como este [w / Google? Samsung?]? ¿O es StackOverflow mi mejor oportunidad de encontrar una respuesta real?
- APIs en android para Bluetooth Servicio de alerta inmediata en Find me profile
- BluetoothAdapter ActionDiscoveryFinished
- ¿Es posible intercambiar mensajes entre 2 dispositivos Android a través de wifi?
- Uso de Bluetooth en el emulador de Android
- Cómo obtener dispositivos conectados a bluetooth mediante BluetoothHeadset API
- Cómo habilitar la funcionalidad de receptor A2DP en Android?
- android sensortag azimut para la brújula no está funcionando (código java)
- La conexión BluetoothSocket de Android devuelve cero
Hay muchas cosas que faltan en la documentación de Android, sin embargo, si llama a startBluetoothSco () y stopBluetoothSco () cada vez durante el enrutamiento de audio no debería haber ningún problema en el encaminamiento del audio correctamente. Incluso he visto cuando la conexión se mantiene inactiva por mucho tiempo y empezamos StartBluetoothSco () directamente obtener desconexión. Para resolver esto escribí una solución que está aquí: https://github.com/kodered/Bluetooth-Refresh-Logic
Espero que esto ayude.
- Android ¿Es posible definir un mapa en un archivo XML?
- Cómo cambiar el menú emergente del color de fondo android