2012-10-04 644 views
15

He creado un acuerdo de recompra GitHub con un proyecto de ejemplo que muestra el problema de abajo estoy preguntando por aquí:
https://github.com/paulpv/audio-loopback/tree/simplified/src/com/twistpair/wave/experimental/loopback
(por favor, se adhieren w/la rama “simplificado” y la indiferencia la rama “master”)Android startBluetoothSco que no empiezan sco pero isBluetoothScoOn devuelve verdadero

los dos archivos principales son:

responsabilidad: actualmente estoy usando sólo una única Samsung Epic SPH-D700 corriendo CyanogenMod 10 Jelly Bean para codificar y probar esto con. No lo he probado en otros dispositivos, pero tal vez eso podría ayudar a evitar que me quite el pelo y me vuelva loco.

he estado luchando conseguir Android Bluetooth SCO a fiable de arranque y parada y captura/reproducción de audio MESES PARA!
Una vez que puedo poner el teléfono en el modo SCO, capturar y reproducir a través de AudioRecord y AudioTrack (respectivamente) funciona bien según lo documentado.
¡El problema que tengo es que no puedo conectar el teléfono de manera confiable al modo SCO!

Los ejemplos en "The Internets" para usar startBluetoothSco() y setBluetoothScoOn (true) parecen simples y directos, pero cuando los uso en mi dispositivo casi nunca funcionan de manera confiable.
Creé mi propia aplicación de prueba que no hace más que iniciar y detener SCO, ¡y ni siquiera puedo hacer que funcione de manera confiable!

Mi código está a la escucha de un BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED EXTRA_STATE==CONNECTED.
Puedo detectar con fiabilidad si algún auricular está conectado o desconectado.

Al detectar una conexión, mi controlador 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 simplemente da como resultado una transición de DISCONNECTED->CONNECTING->DISCONNECTED.

aquí está mi resultado del registro de anotaciones de mi aplicación de ejemplo 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 w/auricular Jawbone apaga y se 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 

. ..UI actualización realizada
Difusión permanente que me dice el actual 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 actual == DESCONECTADO; esperado, ya que mi auricular está apagado.
Se llama a mi detector de eventos desconectado SCO 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 hace

Después de ~ 20 segundos se enciende el 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) 

quijada conectada; 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 auto-llamadas startBluetoothSco()
¡AQUÍ ES DÓNDE ESTÁ EL PROBLEMA! ¿Por qué esta llamada a startBluetoothSco no da como resultado 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 detector de eventos termina hasta w/a sendMessage para actualizar la interfaz de usuario w/el estado actual de BT ...

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 hace
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) 

... trasladaron de DESCONECTADO a CONEXIÓN
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 

... trasladaron de la conexión a DESCONECTADO
lo haría esperaba que SCO pasara de CONECTAR al CONECTADO!
Mi detector de eventos se llama y actualiza la interfaz de usuario w/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 hace

espero ~ 20 segundos para SCO pero conectados nunca viene.
Presiono el botón "startBluetoothSco" de mi aplicación.
TEN EN CUENTA QUE ESTO RESULTA EN LA EXACTA MISMA LLAMADA PARA INICIAR BluetoothSco() AT 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(); 

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) 

... trasladaron de DESCONECTADO a CONEXIÓN
Aquí es donde las cosas se diferencian de la auto-llamada de startBluetoothSco() a las 17: 00: 37.626
Obtenemos un BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED evento ...

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) 

... trasladaron de DESCONECTADO a CONEXIÓN
Tenemos 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) 

. ..movimiento de CONEXIÓN a CONECTADO
Evento actualiza la interfaz de usuario w/un 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 hace (Para ser honesto, no estoy seguro de lo que se llama una segunda vez isBluetoothScoOn)

10-03 17:01:02.603: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=true 

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 

... movido de CONEXIÓN a CONECTADO

FINALIZADO!
Mi detector de eventos se llama y actualiza la interfaz de usuario w/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 hace

Todo (esta vez) funciona cuando " manualmente "inicie SCO después de un tiempo, pero no si inicio automáticamente SCO inmediatamente después de conectar un auricular.

Para empeorar las cosas, cuando las cosas no están funcionando como se esperaba veo un comportamiento extraño en el SCO afirma:

  • Retrasar la startBluetoothSco() durante 3-5 segundos razonables parece 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 sus auriculares BT es ridículo.
  • A veces la llamada esBluetoothScoOn() devuelve verdadero, incluso cuando nunca he recibido un evento de transmisión desde el último estado DESCONECTADO diciendo que el estado cambió a CONECTADO.
  • A veces la llamada "manual" a startBluetoothSco() desde la IU no hace nada, como si SCO ya estuviera activado, pero nunca recibí ningún evento de transmisión desde el último estado DESCONECTADO que indica que el estado cambió a CONECTADO.
  • Al intentar abrir AudioTrack o AudioRecord no se produce ningún sonido (este mismo código funciona bien cuando SCO no se comporta mal, es decir, el problema es el estado SCO, no las llamadas AudioTrack/AudioRecord).
  • Llamar a stopBluetoothSco() no provoca ningún evento que informe el estado DESCONECTADO.
  • setBluetoothScoOn (falso/verdadero) no hace ninguna diferencia. Para ser sincero, no entiendo la diferencia en el aparentemente redundante "startBluetoothSco()/stopBluetoothSco()" y "setBluetoothScoOn (boolean)". Cuando las cosas funcionan, mi llamada startBluetoothSco() hace que isBluetoothScoOn() devuelva verdadero y me hace pensar que no necesito llamar a setBluetoothScoOn (true).
  • Reiniciar el teléfono no hace ninguna diferencia.
  • Reiniciar los auriculares no hace ninguna diferencia.
  • Cambiar a otro auricular no hace diferencia.
  • A veces, el auricular pierde su emparejamiento y debe volver a emparejarse.

Teniendo en cuenta la trayectoria de Google/Android en soporte de Bluetooth, muy poco de esto me sorprende.

¿Alguien puede por favor sacarme de mi miseria y definitivamente explicarme cómo iniciar y detener con confianza el SCO bluetooth en Android?

PD: ¿Hay un canal oficial para escalar problemas como este [w/Google? Samsung?]? O, ¿StackOverflow es mi mejor oportunidad de encontrar una respuesta real?

+1

He ejecutado este mismo código en comparación con un Motorola RAZR que ejecuta ICS y tiene exactamente los mismos o peores resultados. En este Motorola RAZR, ni siquiera puedo "iniciar" manualmente startBluetoothSco() para pasar de SCO_AUDIO_STATE_CONNECTING-> SCO_AUDIO_STATE_CONNECTED. – swooby

+0

También probé esto en un auricular Samsung HM1700 y un auricular Jawbone no A2DP. Diferentes teléfonos, auriculares diferentes; Exacto mismo [o peor] resultados. :( – swooby

+0

Tengo el problema exacto, solo puedo decirte que tengo un código similar al tuyo que funciona en Samsung Galaxy Mini con Gingerbread y funciona pero el mismo código no funciona en absoluto en Jellybean. – Ahmed

Respuesta

2

Faltan muchas cosas 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 problemas para enrutar el audio correctamente. Incluso he visto cuando la conexión se mantiene inactiva por mucho tiempo y comenzamos StartBluetoothSco() nos desconectamos directamente. Para resolver esto escribí una solución que está aquí: https://github.com/kodered/Bluetooth-Refresh-Logic

Espero que esto ayude.

+0

Después de dos años sin respuesta, no he probado su solución, ¡pero voy a darle crédito por esta! – swooby

Cuestiones relacionadas