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:
- 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
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?
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
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
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