安卓:蓝牙UUID是如何工作的?

90
我不理解蓝牙UUID代表什么。UUID代表协议吗(例如RFCOMM)?如果是这样,那么为什么createRfcommSocketToServiceRecord()方法需要UUID,当它们在名称中已经指定了rfcomm?为什么BluetoothChat示例代码有一个看似任意的硬编码UUID?
我的问题是因为根据this question,当设备运行4.0.4时,尝试使用反射连接(到外部非Android设备)时,我会得到一个空指针异常。然而,那个问题的解决方案对我不起作用。UUID muuid = device.getUuids()[0].getUuid();引发了一个异常。

编辑:我通过硬编码UUID解决了串行端口服务的问题,如此答案所述(使用UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");)。

我进一步困惑的是,为什么我需要提供一个UUID来创建一个未加密的rfcomm套接字,使用createInsecureRfcommSocketToServiceRecord(),但不使用反射方法。

有人能给我解释一下吗?


3
这就是我所知道的蓝牙UUID,你可以阅读这份PDF来更好地了解蓝牙协议和UUID - http://people.csail.mit.edu/rudolph/Teaching/Articles/PartOfBTBook.pdf - 0xC0DED00D
嘿嘿嘿!我想问一些问题,@ForeverWintr,如果我定义一个带有自己格式的单个UUID并在两个Android设备中使用,这样可以吗?我的意思是,它们能够相互通信吗? - gumuruh
@gumuruh,我不知道!也许你应该开一个新的问题? - ForeverWintr
要通过SDP查找远程设备支持哪些uuid,请使用fetchUuidsWithSdp()与ACTION_UUID广播接收器,而不是getUuids();后者用于获取本地Android设备支持的Uuid。每个值得注意的服务(如A2DP)都有一个通用的Uuid,Android可以识别,因此制造商不必每次都发出自定义应用程序以允许uuid匹配。这就是Android如何自动识别耳机和键盘的方式。 - Kevin Lee
那么为什么两个客户端 Android 设备不能使用相同的 UUID 连接到同一主机设备? - behelit
显示剩余3条评论
7个回答

33

UUID用于唯一标识信息,可以标识蓝牙设备提供的特定服务。标准定义了一个基本的BASE_UUID: 00000000-0000-1000-8000-00805F9B34FB

像医疗感应器这样的设备可以提供服务,将前八个数字替换为预定义代码。例如,提供RFCOMM连接的设备使用短代码:0x0003

因此,Android手机可以连接到设备,然后使用服务发现协议(SDP)查找它提供的服务(UUID)。

在许多情况下,您不需要使用这些固定的UUID。例如,如果您正在创建聊天应用程序,则一个Android手机与另一个使用相同应用程序和相同UUID的Android手机进行交互。

因此,您可以使用任意UUID为您的应用程序设置UUID,例如,在Web上使用许多随机UUID生成器之一(如此例)。


1
RFCOMM服务的完整UUID是:00000003-0000-1000-8000-00805F9B34FB? - gyozo kudor
2
注意:它们列出了服务ID的短格式,该格式为32位。您需要将其与BT SIG的基本UUID 00000000-0000-1000-8000-00805F9B34FB组合,替换GUID的前4个数字。例如,RFCOMM为0x0003,因此RFCOMM服务的UUID为00030000-0000-1000-8000-00805F9B34FB。 - sam msft

24

它通常代表蓝牙设备支持的一些常见服务(协议)。

创建自己的rfcomm服务器(使用listenUsingRfcommWithServiceRecord)时,应指定自己的UUID,以便连接到它的客户端可以识别它;这是createRfcommSocketToServiceRecord需要UUID参数的原因之一。

否则,一些常见服务具有相同的UUID,只需找到所需的一个并使用即可。

请参见此处


3
我不明白的是,如果我正在创建一个RCOMM服务器,为什么不使用RFCOMM UUID。 "it usually does?"的意思是通常会这样做,那么什么情况下不会这样做呢? - ForeverWintr
1
UUID通用唯一标识符。RFCOMM 只是蓝牙协议栈上的一个层,其关联的 UUID 符合蓝牙规范;并由 SDP 使用,我不是完全确定它的用途; 但您可以在规范中了解到相关信息。如果您正在基于 RFCOMM 协议创建服务,则必须提供 UUID,因为 SDP 要求如此,否则您的服务将无法被发现。 - nullpotent
3
在网上找到了这个链接,它列出了蓝牙服务的所有UUID。链接地址为:http://sviluppomobile.blogspot.de/2012/11/bluetooth-services-uuids.html。 - Orri
链接已失效 - 它是常见UUID列表吗? - user1725145

16
在蓝牙中,所有对象都由UUIDs标识。这些包括服务、特征和许多其他事物。蓝牙维护着用于标准对象的分配号码数据库,并为已支付足够预留的供应商分配子范围。您可以在此处查看此列表:

https://www.bluetooth.com/specifications/assigned-numbers/

如果您正在实现标准服务(例如串口、键盘、耳机等),则应使用该服务的标准UUID,这将使您能够与您未开发的设备进行互操作。
如果您正在实现自定义服务,则应生成唯一的UUID,以确保不兼容的第三方设备不会尝试使用您的服务,认为它是其他东西。最简单的方法是生成随机UUID,然后在应用程序中硬编码结果(当然,在连接到您的服务的设备中也要使用相同的UUID)。

我从哪里获取这些UUID,为什么它们总是看起来像随机字符串? - luke cross
1
UUID是根据RFC 4122生成的。有五个不同的UUID版本可供选择。最流行的是版本1(基于时间戳和MAC地址)和版本4(随机)。另请参见http://en.wikipedia.org/wiki/Universally_unique_identifier。一个可以为您生成UUID的网页是http://uuidgenerator.net。如果您是Bluetooth SIG成员,则他们提供了一个算法来生成与您的会员ID相关联的UUID。 - David C.

8

UUID类似于互联网中的端口号。但是,蓝牙和互联网之间的区别在于,在蓝牙中,端口号是由SDP(服务发现协议)服务器动态分配的,每个UUID都被赋予一个端口号。其他设备将询问注册在预留端口号下的SDP服务器,了解设备上可用的服务,并通过不同的已注册UUID来区分彼此的不同服务。


4

UUID只是一个数字,除非你在Android应用程序的服务器端创建了它,否则它没有任何意义。然后,客户端使用相同的UUID进行连接。

例如,在服务器端,您可以首先运行uuid = UUID.randomUUID()来生成一个随机数,如fb36491d-7c21-40ef-9f67-a63237b5bbea。然后保存该值,并在监听程序中像这样硬编码:

 UUID uuid = UUID.fromString("fb36491d-7c21-40ef-9f67-a63237b5bbea"); 

您的Android服务器程序将以以下方式监听具有该UUID的传入请求:
    BluetoothServerSocket server = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("anyName", uuid);

BluetoothSocket socket = server.accept();


2
UUID代表通用唯一标识符。UUID是一个简单的128位数字,分布在全球,并且具有独特性。
蓝牙通过空气发送数据,所有附近的设备都可以接收到它。假设你有时必须通过蓝牙发送一些重要文件,而所有附近的设备都可以在范围内访问它。因此,当您与其他设备配对时,它们会简单地共享UUID号码并进行匹配,然后再共享文件。当您发送任何文件时,您的设备会使用适当的设备UUID加密该文件并在网络上共享。现在,范围内的所有蓝牙设备都可以访问加密文件,但他们需要正确的UUID号码。因此,只有正确的UUID设备才能访问加密文件,其他设备因为UUID错误而被拒绝。
简而言之,您可以将UUID用作在任何两个蓝牙设备之间共享文件的秘密密码。

1
总之:UUid用于唯一标识应用程序。每个应用程序都有一个独特的UUid
因此,对于每个设备使用相同的UUid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接