蓝牙SDP和UUID如何工作?(专门针对Android)

Leo*_*ang 3 android bluetooth

我的理解是SDP是其他设备可以获取的UUID列表.

根据麻省理工学院的这篇PDF文章,"将SDP视为信息数据库的更通用的方法." 这是否意味着我可以为SDP添加多个值?自Android以来BluetoothDevice.fetchUuidsWithSdp(),如何设置设备的UUID?

另外,UUID的每个部分是什么意思?UUID看起来像00000000-0000-1000-8000-00805F9B34FB,但这传达了什么信息?

hgr*_*oss 12

UUID标识特定设备上可用的服务.因此,如果您调用BluetoothDevice.fetchUUidsWithSdp()您的BroadcastReceiver将收到包含设备和服务UUID 的相关Intent ACTION_UUID.蓝牙规范定义了一些常见的UUID.

如果您不想连接到其中一个众所周知的服务但是想要实现自己的蓝牙应用程序,那么您必须生成自己的UUID(使用来自unix控制台或在线生成器的 uuidgen )来识别您的应用程序/服务.你可以像这样在java中创建一个UUID实例UUID uuid = UUID.fromString("785da8ea-1220-11e5-9493-1697f925ec7b");.

因此,如果您在Android上为蓝牙应用程序创建服务器端,通常会执行此操作

BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("YourHumanReadableServiceName", uuid);
Run Code Online (Sandbox Code Playgroud)

这就是你"设置"你的UUID的地方.Android蓝牙API会为您创建由您的应用程序的UUID和名称组成的SDP条目.其他设备现在可以检索此条目.Androids蓝牙堆栈现在将蓝牙通道与您的BluetoothServerSocket相关联.如果您想要连接到该ServerSocket的,连接侧通常连接做这个:

// you will most likely already have this instance from a discovery or paired device list
BluetoothDevice serverDevice = adapter.getRemoteDevice(bluetoothMacAddress);
// connect to your ServerSocket using the uuid
BluetoothSocket socket = serverDevice.createRfcommSocketToServiceRecord(uuid);
socket.connect();
Run Code Online (Sandbox Code Playgroud)

Android将再次为您做繁重的工作:它检查远程设备上的SDP-Records,查找与您服务的UUID相对应的蓝牙通道,并使用此信息进行连接.

这里有一个常见的代码片段,因此建议您使用"反射"来获取类似于此代码的隐藏API:

 try {
     // this is the way to go
     socket = device.createRfcommSocketToServiceRecord(uuid);
     socket.connect( );
 } catch ( IOException exception ) {
     // don't do that! You will bypass SDP and things will go sideways.
     Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
     socket = (BluetoothSocket) m.invoke(device, 1);
     socket.connect();
 }
Run Code Online (Sandbox Code Playgroud)

大多数人尝试这一点,它在开发环境中"正常工作",但你应该知道你用它做了什么.您主动绕过SDP查找,检索要与您的服务一起使用的正确蓝牙通道,并且最终将连接到通道1.如果您在设备上运行了多个服务,在这种情况下,事情将会横向进行,您将最终调试地狱;-)

我开发了一个名为Blaubot的小型中间件来使用bluetooth/wifi/nfc创建小型网络,并在我曾经测试过的设备(12个型号)上遇到各种各样的问题.通常的情况是蓝牙堆栈在它有一些负载或多次连接/断开连接的情况下不再具有完全功能(如果你正在开发你的应用程序,通常会有这种情况).在这些情况下,device.createRfcommSocketToServiceRecord(uuid)偶尔会出现故障并且仅关闭蓝牙适配器并再次打开有助于使蓝牙适配器恢复生命(在某些情况下仅在完整的电源循环后).如果发生这种情况并使用反射方法,那么蓝牙可能不会有太多乐趣.

但是如果您知道这一点并且在边界内保持对BluetoothAdapter的并发呼叫,则蓝牙连接和适配器将非常稳定.