2012-10-04 21 views
15

我創建了一個GitHub庫與示例項目,顯示了下面的問題我問這裏:
https://github.com/paulpv/audio-loopback/tree/simplified/src/com/twistpair/wave/experimental/loopback
(請堅持瓦特/「簡化」分支和無視「主」分支)的Android startBluetoothSco無法啓動SCO但isBluetoothScoOn返回true

兩個主要文件是:

聲明:我目前只使用一臺運行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看到,但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) 

我的應用程序啓動W/Jawbone耳機關閉,更新UI ...

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

。 ..UI更新完成
粘滯廣播告訴我當前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 ==斷開;預計,因爲我的耳機已關閉。
我的SCO斷開事件監聽器被調用並更新UI w /兩個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 

... UI更新完成

後〜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 ==關連?!?!

10-03 17:00:37.626: D/AudioStateManager(29487): startBluetoothSco() 
10-03 17:00:37.626: I/AudioStateManager(29487): mAudioManager.startBluetoothSco(); 

我的事件監聽器完成了W/A SendMessage函數更新UI瓦特/當前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 

... UI更新完成
從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 

...從連接到DISCONNECTED移動
我會預計SCO將從連接轉到連接
我的事件監聽器被調用和更新UI w^/兩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 

... UI更新完成

我等待約20秒SCO連接,但它永遠不會來。
我按下我的應用程序的「startBluetoothSco」按鈕。
注意,這將導致完全相同的調用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(); 

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

...斷開連接移動在連接
這裏是東西從自動呼叫不同17:00的startBluetoothSco():37.626
我們得到一個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) 

...斷開連接移動在連接
我們得到另一個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) 

。 ..從連接移動到連接
事件更新UI瓦特/一個的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 

... 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 

...從連接移到連接

最後!
我的事件監聽器被調用和更新UI w^/兩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 

... UI更新完成

一切(這一次)的作品,當我「手動「在一段時間後啓動SCO,但如果在連接耳機後立即自動啓動SCO,則不會。

更糟糕的是,當事情如預期我看到在SCO奇怪的行爲不工作狀態:

  • 延緩startBluetoothSco()爲合理的3-5秒似乎有什麼區別。我還沒有嘗試過超過5秒。等待超過5秒讓音頻開始流向您的BT耳機是可笑的。
  • 有時調用isBluetoothScoOn()返回true,即使從上次DISCONNECTED狀態以來我從未收到過廣播事件,說明狀態已更改爲CONNECTED狀態。
  • 有時,從UI手動調用startBluetoothSco()不會執行任何操作,就好像SCO已經打開一樣,但自從最後一次DISCONNECTED狀態聲明狀態更改爲CONNECTED以來,我從未收到任何廣播事件。
  • 試圖打開AudioTrack或AudioRecord結果沒有聲音(當SCO沒有行爲不端時,相同的代碼工作正常,即:問題是SCO狀態,而不是AudioTrack/AudioRecord調用)。
  • 調用stopBluetoothSco()不會導致任何事件報告狀態DISCONNECTED。
  • setBluetoothScoOn(false/true)沒有區別。說實話,我不明白在看起來多餘的「startBluetoothSco()/ stopBluetoothSco()」和「setBluetoothScoOn(布爾)」中的區別。當事情正常時,我調用startBluetoothSco()會導致isBluetoothScoOn()返回true,使我認爲我不需要調用setBluetoothScoOn(true)。
  • 重新啓動手機沒有任何區別。
  • 重新啓動耳機沒有區別。
  • 更換爲其他耳機沒有區別。
  • 有時耳機失去了配對,必須重新配對。

鑑於對藍牙的支持谷歌的/ Android的跟蹤記錄,很少的這令我感到奇怪。

有人可以讓我擺脫我的痛苦,並明確解釋如何可靠地啓動和停止在Android藍牙SCO?

PS:有沒有正式的渠道來升級像這樣的問題[谷歌?三星?]?或者,StackOverflow是我找到實際答案的最佳機會?

+1

我對運行ICS的摩托羅拉RAZR運行相同的代碼,它具有完全相同或更差的結果。 在這摩托羅拉RAZR我甚至不能「手動」讓startBluetoothSco()從SCO_AUDIO_STATE_CONNECTING-> SCO_AUDIO_STATE_CONNECTED去。 – swooby

+0

我也在三星HM1700耳機和Jawbone非A2DP耳機上試了這個。 不同的手機,不同的耳機;完全相同[或更差]的結果。 :( – swooby

+0

我有確切的問題,我只能告訴你,我有一個類似的代碼給你的工作在三星Galaxy Mini與薑餅,它的作品,但相同的代碼根本不工作在果凍豆。 – Ahmed

回答

2

Android文檔中缺少很多東西,但是,如果您在音頻路由期間每次調用startBluetoothSco()和stopBluetoothSco(),則應該沒有問題正確地路由音頻。 即使我看到連接長時間保持閒置狀態,我們啓動StartBluetoothSco(),我們直接斷開連接。 爲了解決這個問題,我寫了一個解決方法,這裏是:https://github.com/kodered/Bluetooth-Refresh-Logic

希望這會有所幫助。

+0

經過兩年沒有答案,我還沒有測試您的解決方案,但我會給你這個榮譽! – swooby