在Android中通过蓝牙接收音频



我想创建一个能够接收音频流的Android应用程序。我想使用A2DP配置文件,但似乎Android不支持A2DP接收器。看起来有很多人在寻找解决这个问题的方法。但是如果接收一个普通的比特流,然后在应用程序中将数据转换为音频呢?我正在考虑通过RFCOMM (SPP蓝牙配置文件)接收PCM或Mp3数据流,然后使用AudioTrack播放。

首先,我如何通过RFCOMM在我的Android手机上接收比特流?有可能通过RFCOMM接收位流作为PCM或Mp3流吗?

第二,如果不可能通过RFCOMM接收作为PCM或Mp3流的位流,我如何将接收的位流转换为音频?

第三,我如何将接收到的数据转换成音频并同时播放音频,在"实时"?我可以只使用onDataReceived吗?

澄清一下,我对使用A2DP配置文件不感兴趣!我想通过RFCOMM (SPP蓝牙配置文件)流式传输数据。接收到的数据流将是PCM或Mp3格式。我想写自己的应用程序,但如果有人知道一个应用程序来解决这个问题,我很高兴听到它!我用的是安卓2.3姜饼。

/约翰尼

尝试编写一个Android应用程序来处理这将不是解决方案。至少如果你想使用A2DP Sink角色。

事实是,Android,正如你提到的,没有实现API调用BlueZ(蓝牙堆栈Android使用直到果冻豆4.1)关于A2DP sink的能力。你必须自己实现它们。我将尝试指导你,因为我也有兴趣这样做我自己在不久的过去。

默认情况下,您启用蓝牙的Android设备将自己宣传为A2DP source设备。您必须首先更改此设置,以便附近的设备可能将您的设备识别为接收器。为此,您必须修改audio.conf文件(通常位于/etc/bluetooth/),并确保Enable密钥存在,并且值Source附加到该密钥上,因此您将得到如下内容:

Enable=Source

重新启动,附近的设备现在应该将您的设备识别为A2DP sink

现在,当A2DP源设备开始将音频流式传输到您的手机时,您将不得不与BlueZ进行交互以做出适当的反应。

Android和BlueZ通过D-BUS相互通信。事实上,Android连接到DBUS_SYSTEM通道并监听每个BlueZ广告,例如事件,文件描述符…

我记得我曾经用一个本地应用程序成功地将我自己绑定到这个d-bus通道,并访问了BlueZ发布的各种事件。使用此处提供的BlueZ API作为参考,这相对容易实现。如果采用这种方法,您将不得不构建一个本机应用程序(C/c++),并为您的平台编译它。您必须能够使用Android NDK .

执行此操作。

如果你发现很难使用D-BUS,你可以尝试这个Java库,我刚刚发现处理通信到D-BUS为您:http://jbluez.sourceforge.net/。我从来没用过,但我觉得值得一试。

你真正要做的是找出A2DP源设备何时与你的手机配对,以及他何时开始流媒体音乐。您可以通过D-BUS检索这些事件。一旦有人尝试流媒体音乐,你需要告诉BlueZ你的本机应用程序将会处理它。有一个非常好的文档解释了您应该处理的事件流。这份文件可以在这里找到。你感兴趣的部分在第七页。在给定的示例中的接收器应用程序是PulseAudio,但它也可以是您的应用程序。

当您调用org.bluez.MediaTransport.Acquire方法时,BlueZ将向您转发一个UNIX套接字。读取此套接字将为您提供远程设备当前流式传输的数据。但我记得有一个在BlueZ堆栈上工作的人告诉我,在这个套接字上读取的数据不是PCM纯音频,而是编码的音频内容。数据通常以SBC (低复杂度子带编码)的格式编码。

解码SBC并不难,你可以在这里找到解码器。

最后一步是将PCM音频转发到您的扬声器。

为了防止你卡住,为了以一种更容易的方式测试你的应用程序,你可以使用d-bus二进制文件,它应该在你的Android系统上可用。他位于/系统/bin

在执行上述任何操作之前,您可以做以下快速测试:

获取设备列表:

dbus-send——system——dest=org。Bluez -打印-回复/org.bluez.Manager.GetProperties

返回一个适配器数组及其路径。一旦你有了这些路径,你就可以检索与你的适配器配对的所有蓝牙设备的列表。

获取配对设备:

dbus-send——system——print-reply——dest=org.bluez/org/bluez/{pid}/hci0 org.bluez.Adapter.GetProperties

给出devices数组字段中配对设备的列表。

一旦你有了蓝牙适配器配对的设备列表,你就可以知道它是否连接到AudioSource接口。

获取AudioSource接口连接的设备:

dbus-send——system——print-reply——dest=org.bluez/org/bluez/{pid}/hci0/dev_XX_XX_XX_XX_XX_XXorg.bluez.AudioSource.GetPropertiesorg.bluez.Manager.GetProperties

希望这对你有帮助。

另一种方法是使用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();

[无关但有效]此hack仅通过WIFI热点提供mp3流(我在只有AUX输入的汽车中使用它):

  1. 安装AirSong应用程序,
  2. 打开wifi热点,
  3. 将其他设备连接到该热点,
  4. 从设备的浏览器访问192.168.43.1:8088,你就打开了。

(想知道为什么只有"192.168.43.1"?

audio.conf似乎在Android 4.2.2中丢失了?

要通过rfcomm接收pcm音频流,您可以使用代码流作为提示解释(在C中读取音频文件并通过蓝牙转发到Android音频轨道中播放),并进行更改。将初始化时使用的频率从44100更改为22050

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

注意:此流仍然包含一些噪声,但您的

"通过RFCOMM (SPP蓝牙配置文件)接收PCM数据流,然后使用AudioTrack播放。"

相关内容

  • 没有找到相关文章

最新更新