android蓝牙编程 重点知识 SPP A2DP UUID

来源:互联网 发布:电视机如何看网络电视 编辑:程序博客网 时间:2024/05/10 05:51

蓝牙编程很简单,步骤如下:

(1).获得本机蓝牙设备:BluetoothAdapter mBTAdp = BluetoothAdapter.getDefaultAdapter();;

(2)注册一个发现设备的回调函数

getActivity().registerReceiver(mBroadcastReceiver,intentFilter);

(3)开始搜索设备:mBTAdp.startDiscovery();在Listview中显示结果,点击具体条目时,返回蓝牙地址:mAddr 

(4)通过mAddr获得远程设备:BluetoothDevice mBTRemoteDev  = mBTAdp.getRemoteDevice(mAddr); //其中mAddr

(5)通过远程设备的对象,获得Socket:mBTSocket = mBTDevInThread.createRfcommSocketToServiceRecord(uuid);

网上有很多参考代码,例如:http://blog.csdn.net/xzongyuan/article/details/39318649。


本文总结研究android蓝牙编程中的疑惑:

1.rfcomm有什么作用?它是蓝牙客户端和服务端的Socket通道。设备pair(配对后),在android中只是bondedDevice,还没有通信通道。因此,RFCOMM是了解蓝牙通信的基础。参考http://www.go-gddq.com/down/2013-06/13062113071155.pdf

RFCOMM是一个简单传输协议,其目的为了解决如何在两个不同设备上的应用程序之间保证一条完整的通信路径,并在它们之间保持一通信段的问题。

2.BluetoothServerSocket是什么东西?它返回BluetoothSocket,类似于SocketServer,TCP通信业会用到ServerSocket。它的作用就是监听其他蓝牙设备的接入,一旦有蓝牙设备主动发起建立RFCOMM信道,它就会返回一个"新的"对应的BluetoothSocket。

使用办法,因为是监听,所以函数名是listen

BluetoothServerSocket tmp ;
tmp =mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);mmServerSocket =tmp;
mmServerSocket调用accept进行监听,是阻塞操作,一旦有设备发起请求,就会返回一个Socket,这个Socket也是阻塞操作,因此需要新建一个独立线程进行处理。

01while(true){
02 BluetoothSocket  socket;
03            socket = mmServerSocket.accept();                 // If a connection was accepted        
04  if (socket!= null){              
05    // Do work to manage the connection (in a separate thread)               
06    manageConnectedSocket(socket);               
07    mmServerSocket.close();              
08    break;       
09   }    
10}


3.UUID是什么?一个uuid对应一种service,在蓝牙4.0的datasheet中有定义UUID的格式,哪个bit代表什么功能都有清楚定义,而且有很多常用的服务已经根据datasheet定义好了值,所以你上网会查到UUID表;不过,理论上,只要两台设备UUID是一致的,就能建立socket。统一格式,只是提高设备间的兼容性,避免不同service碰巧被定义为相同的uuid了。android提供的Sample——BluetoothChat就是自定义的。而一般情况,还是得符合UUID的规范,例如我设计的SPP协议通信,这是蓝牙数据传输的基本协议,我只需要查到SPP的uuid为:

static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";

我就不用管其他设备的情况了。例如我设计的一块开发板,压根就没提供uuid,只是提供spp的api,如果没有统一的uuid,我就无法进行通信了。


4.蓝牙传输和蓝牙音频如何同时开启?这是我的一个疑问,我用createRfcommSocketToServiceRecord创建了一个Socket链接请求,但是成功后,我只能发数据,不能把手机音频传到开发板。我在想,必定有某个地方创建了音频Socket,可能是A2DP,使得音频可以顺利传输。经过百般搜索,终于找到个不错的链接

https://www.bluetooth.org/zh-cn/specification/assigned-numbers/service-discovery

AudioSource0x110A高级音频分发配置文件(A2DP)服务类AudioSink0x110B高级音频分发配置文件(A2DP)服务类SerialPort0x1101串口配置文件(SPP)
注:SPP 1.0版中的SDP记录范例并不包含BluetoothProfileDescriptorList属性,但部分实施中也可将此UUID用于配置文件标识符。服务类/配置文件从上面的定义可以看到,AudioSource和AudioSink就是A2DP的配置名称,我把SPP的UUID改一下就得到A2DP的UUID了

static final String SPP_UUID                = "00001101-0000-1000-8000-00805F9B34FB";

static final String A2DP_SRC_UUID  = "0000110A-0000-1000-8000-00805F9B34FB";
static final String A2DP_SINK_UUID  = "0000110B-0000-1000-8000-00805F9B34FB";


5.Socket connect faild怎么处理?我之前在用getBondedDevices获得已经pair的设备,然后连接,当只有一台设别时,不需要辨别。但当我安装APP到一台已经配对了2个设备的Tablet上,发现,Socket Connect time out 了。原因是,getBondedDevice返回的是一个BluetoothDevice设备Set,我刚好获得另外一个BluetoothDevice(不是我想连接的那台),而另一台设备蓝牙没打开,以至于我创建的Socket连接不上。


6.怎么同时启动SPP和音频A2DP功能?研究了1天,终于找到办法了,用反射机制把Android隐藏API调用出来,即可,实现代码:

http://blog.csdn.net/xzongyuan/article/details/39344953


参考资料:

如果能翻墙,最好去官网看Reference API,讲的比较全。

http://blog.csdn.net/flyfish10000/article/details/5796168

http://blog.csdn.net/xzongyuan/article/details/39318649

0 0
原创粉丝点击