2012-10-04 21 views
15

ho creato un repo GitHub con un progetto di esempio che mostra il problema di seguito chiedo circa qui:
https://github.com/paulpv/audio-loopback/tree/simplified/src/com/twistpair/wave/experimental/loopback
(si prega di bastone w/il ramo “semplificata” e disprezzo il ramo “master”)Android startBluetoothSco non di partenza sco ma isBluetoothScoOn restituisce true

I due file principali sono:

Diniego: Attualmente sto solo usando un singolo Samsung Epic SPH-D700 esecuzione CyanogenMod 10 Jelly Bean per codificare e testare questo con. Non ho provato questo su altri dispositivi, ma forse questo potrebbe aiutare a impedirmi di tirare fuori i miei capelli e impazzire.

mi batto ricevendo Android Bluetooth SCO per affidabile start e stop e la cattura/riproduzione audio PER MESI!
Quando riesco ad accedere al telefono in modalità SCO, l'acquisizione e la riproduzione tramite AudioRecord e AudioTrack (rispettivamente) funzionano bene come documentato.
Il problema che sto avendo è che non riesco a far entrare in modo affidabile il telefono in modalità SCO!

Gli esempi su "The Internet" per utilizzare startBluetoothSco() e setBluetoothScoOn (true) sembrano tutti semplici e diretti, ma quando li utilizzo sul mio dispositivo non funzionano quasi mai in modo affidabile.
Ho creato la mia app di prova che non fa altro che avviare e arrestare SCO e non riesco nemmeno a farlo funzionare in modo affidabile!

Il mio codice ascolta BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED EXTRA_STATE==CONNECTED.
È possibile rilevare in modo affidabile quando un auricolare è connesso o disconnesso.

Durante il rilevamento di una connessione, il gestore chiama immediatamente startBluetoothSco().
A potrebbe giurare che almeno una volta questo ha calciato SCO_AUDIO_STATE a C O NNECTED, ma il 99% delle volte risulta solo in una transizione da DISCONNECTED->CONNECTING->DISCONNECTED.

Qui è la mia uscita di registro annotato dalla mia GitHub campione app:

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) 

mia app inizia w/auricolare Jawbone spento e aggiorna l'interfaccia utente ...

10-03 17:00:16.568: D/MainActivity(29487): updateScreen()... 
10-03 17:00:16.572: D/AudioStateManager(29487): mAudioManager.isBluetoothScoOn()=false 

. ..Un aggiornamento fatto
Trasmissione appiccicosa che mi dice l'attuale 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 corrente == SCOLLEGATO; previsto, poiché il mio auricolare è spento.
Il listener di eventi SCO disconnesso viene chiamato e aggiorna l'interfaccia utente con due messaggi send ...

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 

... aggiornamento dell'interfaccia utente fatto

Dopo ~ 20 secondi accendo il mio auricolare 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 collegato; Il mio listener di eventi si chiama ...

10-03 17:00:37.626: I/MainActivity(29487): onBluetoothHeadsetConnected() 

... vede che siamo in grado di SCO ...

10-03 17:00:37.626: D/AudioStateManager(29487): mAudioManager.isBluetoothScoAvailableOffCall()=true 

... e auto-chiama startBluetoothSco()
ECCO DOVE È IL PROBLEMA! Perché questa chiamata a startBluetoothSco non risulta in 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(); 

mio listener di eventi finisce su w/a sendMessage per aggiornare l'interfaccia utente w/l'attuale stato di 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 

... aggiornamento dell'interfaccia utente fatta
Primo risultato da startBluetoothSco entra in ...

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) 

... spostato da ESTRATTO alla COLLEGAMENTO
Secondo risultato da startBluetoothSco entra in gioco ...

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 

... spostato di connettersi a SCOLLEGATO
lo farei mi aspettavo che SCO passasse da CONNECTING a CONNECTED!
mio listener di eventi viene chiamato e aggiorna l'interfaccia utente w/due 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 

... aggiornamento dell'interfaccia utente fatta

Aspetto ~ 20 secondi per SCO collegati ma non viene mai.
Premere il pulsante "startBluetoothSco" della mia app.
NOTA CHE QUESTO RISULTA ESATTAMENTE NELLO STESSO CHIAMATA per startBluetoothSco() 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(); 

primo risultato da startBluetoothSco entra in gioco ...

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) 

... spostato da ESTRATTO alla COLLEGAMENTO
Qui è dove le cose sono diverse da quelle di auto-call di startBluetoothSco() a 17: 00: 37,626
Otteniamo 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) 

... spostato da ESTRATTO alla COLLEGAMENTO
Otteniamo un altro 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) 

. ..moved from CONNECTING to CONNECTED
evento aggiorna l'interfaccia utente w/uno 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 

... aggiornamento UI fatto (Per essere onesti, io non sono sicuro di quello che sta chiamando isBluetoothScoOn una seconda volta)

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

secondo risultato da startBluetoothSco entra in gioco ...

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 

... spostato da CONNECTING a CONNECTED

FINALMENTE!
mio listener di eventi viene chiamato e aggiorna l'interfaccia utente w/due 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 

... aggiornamento dell'interfaccia utente fatto

Tutto (questa volta) funziona quando " manualmente "avvia SCO dopo un po 'di tempo, ma non se avvio automaticamente SCO immediatamente dopo aver collegato un auricolare.

A peggiorare le cose, quando le cose non funzionano come previsto Vedo strano comportamento nella SCO afferma:

  • Ritardare l'startBluetoothSco() per 3-5 secondi ragionevoli sembra fare alcuna differenza . Non ho provato a ritardarlo più di 5 secondi. Aspettare più di 5 secondi prima che l'audio inizi a scorrere verso l'auricolare BT è ridicolo.
  • volte chiamando isBluetoothScoOn() restituisce vero, anche se non ho mai ricevuto un evento di trasmissione dal momento che l'ultimo stato DISCONNECTED dicendo quello stato cambiato in Connesso.
  • volte "manualmente" chiamando startBluetoothSco() dall'interfaccia utente non fa nulla, come se SCO è già acceso, ma non ho mai ricevuto alcun evento di trasmissione dal momento che l'ultimo stato DISCONNECTED dicendo quello stato cambiato in Connesso.
  • Prova di aprire o audiotrack AudioRecord risultati in alcun suono (questo stesso codice funziona bene quando SCO non ha un comportamento anomalo es. Il problema è stato SCO, non l'AudioTrack/AudioRecord chiamate).
  • La chiamata a stopBluetoothSco() non comporta la visualizzazione di uno stato di evento DISCONNECTED.
  • setBluetoothScoOn (false/true) non fa alcuna differenza. Ad essere onesti, non capisco la differenza in "startBluetoothSco()/stopBluetoothSco()" apparentemente ridondante e "setBluetoothScoOn (booleano)". Quando le cose funzionano, la mia chiamata startBluetoothSco() restituisce isBluetoothScoOn() restituendo true, facendomi pensare che non ho bisogno di chiamare setBluetoothScoOn (true).
  • Il riavvio del telefono non fa alcuna differenza.
  • Il riavvio dell'auricolare non fa differenza.
  • Il passaggio a un altro auricolare non fa alcuna differenza.
  • A volte l'auricolare perde il suo accoppiamento e deve essere nuovamente associato.

Dato il track record di Google/Android sul supporto Bluetooth, molto poco di questo mi sorprende.

Qualcuno può per favore mi ha messo fuori dalla mia miseria e sicuramente spiegare come avviare e arrestare il bluetooth SCO in Android in modo affidabile?

PS: C'è un canale ufficiale ad aumentare i problemi come questo [w/Google? Samsung?]? Oppure, StackOverflow è la mia migliore possibilità di trovare una risposta effettiva?

+1

Ho eseguito questo stesso codice su un RAZR Motorola che esegue ICS e ha i risultati esatti o peggiori. Su questo Motorola RAZR non riesco nemmeno a "manualmente" avviare startBluetoothSco() per andare da SCO_AUDIO_STATE_CONNECTING-> SCO_AUDIO_STATE_CONNECTED. – swooby

+0

L'ho provato anche con un auricolare Samsung HM1700 e un auricolare Jawbone non-A2DP. Telefoni diversi, cuffie diverse; Risultati esatti [o peggiori]. :( – swooby

+0

Ho il problema esatto, posso solo dirti che ho un codice simile al tuo che funziona su Samsung Galaxy Mini con Gingerbread e funziona ma lo stesso codice non funziona affatto su Jellybean. – Ahmed

risposta

2

Nella documentazione di Android mancano molte cose, tuttavia, se chiamate startBluetoothSco() e stopBluetoothSco() ogni volta durante l'instradamento audio, non dovrebbero esserci problemi nell'instradamento corretto dell'audio. Anche se ho visto quando la connessione viene mantenuta inattiva a lungo e iniziamo StartBluetoothSco(), otteniamo direttamente la disconnessione. Per risolvere questo ho scritto una soluzione alternativa che è qui: https://github.com/kodered/Bluetooth-Refresh-Logic

Spero che questo aiuti.

+0

Dopo due anni di non risposta, non ho testato la tua soluzione, ma ti darò credito per questo! – swooby

Problemi correlati