2013-03-21 203 views
23

我想創建一個能夠接收音頻流的Android應用程序。我想過使用A2DP配置文件,但似乎Android不支持A2DP接收器。看起來有很多人在爲這個問題尋找解決方案。但是接收普通比特流,然後在應用程序中將數據轉換爲音頻呢?我正在考慮通過RFCOMM(SPP藍牙配置文件)接收PCM或Mp3數據流,然後使用AudioTrack進行播放。在Android中通過藍牙接收音頻

首先,我如何通過RFCOMM在我的Android手機上接收比特流?是否有可能通過RFCOMM接收比特流作爲PCM或Mp3流?其次,如果無法通過RFCOMM接收比特流作爲PCM或Mp3流,我如何將接收到的比特流轉換爲音頻?

三,如何將接收到的數據轉換爲音頻,並在「實時」同時播放音頻?我可以使用onDataReceived嗎?

要清楚,我對使用A2DP配置文件不感興趣!我想通過RFCOMM(SPP藍牙配置文件)流式傳輸數據。接收的數據流將採用PCM或Mp3。我想寫自己的應用程序,但如果有人知道一個應用程序來解決這個問題,我很樂意聽到它!我正在使用Android 2.3薑餅。

/約翰尼

+0

嘿約翰尼,到目前爲止沒有什麼進展? ;) – Nippey 2013-12-13 09:44:34

+0

嘿!任何進展? – dpaksoni 2017-05-11 05:45:34

回答

37

試圖寫入一個Android應用程序來處理,這將不會是溶液。至少如果你想使用A2DP Sink角色。

事實上,正如你所提到的,Android並沒有實現對BlueZ(Android使用的藍牙堆棧直到Jelly Bean 4.1)關於A2DP sink功能的API調用。你必須自己實現它們。我會盡力引導你,因爲我也有興趣在過去做我的自我。

默認情況下,支持藍牙的Android設備將自己宣傳爲A2DP source設備。您必須首先更改此設置,以便附近的設備可以將您的設備識別爲接收器。要做到這一點,你必須修改audio.conf文件(usally位於的/ etc /藍牙/),並確保Enable鍵存在和價值Source連接到這個鍵,所以你會得到的東西,如:

Enable=Source 

重啓,附近的設備現在應該認識到您的設備作爲A2DP sink

現在當一個A2DP信號源設備開始向您的手機傳輸音頻時,您將不得不與BlueZ進行互動以做出適當反應。

Android和BlueZ正在通過D-BUS互相交談。事實上,Android連接到DBUS_SYSTEM通道,並收聽每個BlueZ廣告,如事件,文件描述符...

我記得我已經成功地使用原生應用程序綁定到這個d總線通道並獲得訪問BlueZ發佈的各種活動。使用BlueZ API可用here作爲參考,這相對容易實現。如果你這樣做,你將不得不構建一個本地應用程序(C/C++)併爲你的平臺編譯它。您必須能夠使用Android NDK執行此操作。

如果您覺得難以使用D-BUS,您可以試試我剛發現的這個Java庫,它爲您處理與D-BUS的通信:http://jbluez.sourceforge.net/。我從來沒有用過它,但在我看來這是值得一試的。

您真正需要做的是找出A2DP源設備何時與手機配對以及何時開始流式傳輸音樂。您可以通過D-BUS檢索這些事件。一旦有人嘗試傳送音樂,您需要告訴BlueZ您的本機應用程序將處理它。有一個很好的文檔解釋了你應該處理的事件流程。該文檔可以訪問here。您感興趣的部分來自第7頁。在給定示例中的接收器應用程序是PulseAudio,但它也可能是您的應用程序。

當你打電話給org.bluez.MediaTransport.Acquire方法時,BlueZ會給你一個UNIX套接字。讀取此套接字將爲您提供當前由遠程設備傳輸的數據。但是我記得一位在BlueZ堆棧上工作的人告訴我,在這個插座上讀取的數據不是PCM純音頻,而是編碼的音頻內容。數據通常以稱爲SBC(低複雜度子帶編碼)的格式編碼。

解碼SBC不是很困難,你可以找到一個解碼器 right here

最終的步驟是將PCM音頻轉發到揚聲器。

爲了防止您陷入困境,併爲了以更簡單的方式測試您的應用程序,您可以使用應該在Android系統上可用的d-bus二進制文件。他位於/system/bin

快速測試,你可以做的任何事情之前作出上述可能是:

獲取設備列表:

的dbus-發送--system --dest = org.bluez --print -reply/ org.bluez.Manager.GetProperties

這將返回適配器數組及其路徑。一旦你有了這些路徑,你可以檢索與你的適配器配對的所有藍牙設備的列表。

獲得配對的設備:

DBUS-發送--system --print回覆--dest = org.bluez /組織/的bluez/{PID}/hci0 org.bluez.Adapter .GProProperties

這給出了設備陣列字段中配對設備的列表。

一旦你有藍牙適配器配對的設備列表,你可以知道它是否連接到AudioSource接口。

獲取連接到接口的AudioSource設備:

DBUS-發送--system --print回覆--dest = org.bluez /組織/的bluez/{PID}/hci0/dev_XX_XX_XX_XX_XX_XX org.bluez.AudioSource.GetProperties org.bluez.Manager.GetProperties

希望這有助於。

+0

太棒了!我會盡快嘗試。 但我認爲應該可以忽略A2DP並使用RFCOMM。我意識到,我最終可能只是單聲道音頻,但音頻流實際上是一個比特流,不是嗎?那麼爲什麼不使用RFCOMM接收它,然後在我的應用程序中將比特流轉換爲PCM音頻流? – Johnny 2013-03-22 08:02:22

+1

由於A2DP是一種標準,每個手機都默認使用它(即不需要任何應用程序在客戶端工作)。如果您決定使用RFCOMM,我想,您可以提供一個客戶端應用程序,以便從遠程設備傳輸音頻。如果你決定這樣做,你也可以使用wifi通過普通的套接字流式傳輸音頻。Play商店中的許多應用程序都提供了這樣的功能。 – 2013-03-22 08:08:27

+0

這就是說,如果您應用我上面提到的更改,您的接收設備將是唯一的,因爲更改不會在每個Android手機上都可用(除非您使用JNI將另一個BlueZ堆棧封裝在應用程序中,並且仍然是非常困難)。但另一方面,每個設備都可以將音頻流式傳輸到您的接收器。 – 2013-03-22 08:12:27

0

audio.conf似乎在Android 4.2.2中缺失?

+1

從Jellybean開始,bluez堆棧被google替換爲broadcomm藍牙堆棧 – ashish 2013-05-28 10:46:09

+0

在4.1.2中,我提到了上面提到的audio.conf文件。安裝AOKP 4.2.2後,audio.config丟失。 – WoodsLink 2013-06-15 01:03:03

+0

4.2.2包含來自Broadcom的藍牙協議棧,audio.conf是bluez協議棧的一部分[這裏](https://source.android.com/devices/bluetooth.html) – ashish 2013-06-17 04:20:45

0

要通過rfcomm接收pcm音頻流,可以使用代碼流作爲解釋(Reading Audio file in C and forwarding over bluetooth to play in Android Audio track)的提示,並進行更改。而從44100初始化爲22050

AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC,22050,AudioFormat.CHANNEL_OUT_MONO,AudioFormat.ENCODING_PCM_8BIT,10000, AudioTrack.MODE_STREAM); 

說明中使用變化頻率:此流仍然由一些噪音,但你

「通過RFCOMM接收的PCM數據流(SPP藍牙配置文件),然後播放它使用AudioTrack「。

將工作。

1

另一個解決方法是使用HandsFreeProfile。

在Android中,BluetoothHeadset正在處理這個問題。 等待狀態更改爲BluetoothHeadset.STATE_AUDIO_CONNECTED。

然後你就可以從藍牙耳機錄製音頻。

mMediaRecorder = new MediaRecorder(); 
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); 
    mMediaRecorder.setOutputFile(mFilename); 
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
    try { 
     mMediaRecorder.prepare(); 
    } catch (IllegalStateException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    mMediaRecorder.start(); 
+0

你有完整的代碼來連接和設置Android免提?感謝 – user8264 2014-12-11 15:03:21

+0

@ user8264「半滿」 - https://developer.sony.com/develop/wearables/smarteyeglass-sdk/guides/use-bluetooth-for-audio-io/ – Nativ 2016-12-16 16:52:36

1

[無關,但工程]這個黑客僅用通過WIFI熱點的流媒體MP3(我用它在我的車只具有AUX輸入):

  1. 安裝應用AirSong
  2. 打開wifi熱點,
  3. 將其他設備連接到該熱點,
  4. 從設備的瀏覽器訪問192.168.43.1:8088,並喲你在開。

(不知道爲什麼「192.168.43.1」而已?因爲那是連接到Android熱點任何設備的默認網關)