借助 BluetoothAdapter
,
您可以通过设备发现或
查询配对设备列表
确保您拥有适当的蓝牙权限 以及设置应用以使用蓝牙 然后再尝试查找蓝牙设备。
设备发现是一种扫描过程,用于在本地区域中搜索 支持蓝牙的设备,会请求获取每部设备的一些相关信息。这个 过程有时称为发现、查询或扫描。 仅当满足以下条件时,附近的蓝牙设备才会响应发现请求: 接受信息请求。如果设备 它通过共享一些信息来响应发现请求, 例如设备的名称、类别及其唯一 MAC 地址。使用此 信息,执行发现过程的设备可以选择 发起与被发现设备的连接。
由于可检测到的设备可能会泄露用户位置信息, 设备发现过程需要位置信息访问权限。如果用户正在使用您的应用 在搭载 Android 8.0(API 级别 26)或更高版本的设备上,请考虑使用 配套设备管理器 API。此 API 会代表您的应用执行设备发现,因此您的应用无需 请求位置信息权限。
首次与远程设备建立连接后, 请求会自动呈现给用户设备配对后, 该设备的基本信息,例如设备的名称、类别和 MAC 地址 - 已保存,并可使用 Bluetooth API 进行读取。使用已知的 MAC 则可以随时使用该地址发起连接 而不执行发现操作(假设设备仍在范围内)。
请注意,被配对与被连接之间存在区别:
- 被配对意味着两台设备知道彼此的存在, 具有可用于身份验证的共享链接密钥, 与它们建立加密连接。
- 被连接意味着设备当前共享一个 RFCOMM 通道,并且 能够相互传输数据。当前蓝牙 API 要求先对设备进行配对,然后才能 RFCOMM 连接 。当您发起加密会话时,系统会自动执行配对 与 Bluetooth API 进行连接。
以下部分介绍了如何查找已配对的设备 如何使用设备发现功能来发现新设备。
查询已配对设备
在执行设备发现之前,有必要查询
以查看目标设备是否已知。为此,请调用
getBondedDevices()
。
这将返回一组
BluetoothDevice
对象
代表已配对的设备。例如,你可以查询所有已配对的设备
获取每台设备的名称和 MAC 地址,如以下代码段所示
演示:
Kotlin
val pairedDevices: Set<BluetoothDevice>? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach { device -> val deviceName = device.name val deviceHardwareAddress = device.address // MAC address }
Java
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) { String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } }
要发起与蓝牙设备的连接,只需在
关联的 BluetoothDevice
对象是 MAC 地址,供您检索
呼叫
getAddress()
。您
如需详细了解如何创建连接,请参阅连接蓝牙
设备。
发现设备
要开始查找设备,请调用
startDiscovery()
。
该进程为异步进程,并返回一个布尔值,
发现已成功启动。探询过程通常涉及
大约 12 秒的查询扫描,然后对找到的每台设备进行页面扫描
来检索其蓝牙名称。
为了接收每台发现的设备的相关信息,您的应用必须注册
BroadcastReceiver
的
ACTION_FOUND
intent。系统会为每台设备广播此 intent。该 intent 包含
额外字段
EXTRA_DEVICE
和
EXTRA_CLASS
,
又包含 BluetoothDevice
和
BluetoothClass
。
以下代码段展示了如何通过注册来处理广播
当发现设备时:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { ... // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) } // Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action: String = intent.action when(action) { BluetoothDevice.ACTION_FOUND -> { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address } } } } override fun onDestroy() { super.onDestroy() ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) }
Java
@Override protected void onCreate(Bundle savedInstanceState) { ... // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); } // Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address } } }; @Override protected void onDestroy() { super.onDestroy(); ... // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); }
要发起与蓝牙设备的连接,请在getAddress()
BluetoothDevice
可检索关联的 MAC 地址。
启用可检测性
如需使本地设备可被其他设备检测到,请调用
startActivityForResult(Intent, int)
替换为
ACTION_REQUEST_DISCOVERABLE
intent。这会发出启用系统的可检测到模式的请求,
必须导航到“设置”应用,这会停止您自己的应用。修改者
默认情况下,设备在两分钟内会变为可检测到。您可以定义
最长为 1 小时
EXTRA_DISCOVERABLE_DURATION
extra。
以下代码段将设备设置为可检测到,时长为 5 分钟:
Kotlin
val requestCode = 1; val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply { putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) } startActivityForResult(discoverableIntent, requestCode)
Java
int requestCode = 1; Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(discoverableIntent, requestCode);
(
)
图 2:启用可检测性对话框。
系统随即显示一个对话框,请求用户授予创建设备的权限
如图 2 所示。如果用户响应“允许”,然后
在指定的时间段内,设备变为可检测到模式。您之后的活动
收到对
onActivityResult()
回调,其结果代码等于设备在启动
。如果用户回复“拒绝”或出现错误,结果
代码为 RESULT_CANCELED
。
设备在分配的时间内以静默方式保持可检测到模式。待成为
在可检测到模式发生更改时收到通知,注册 BroadcastReceiver
的
ACTION_SCAN_MODE_CHANGED
intent。此 intent 包含 extra 字段
EXTRA_SCAN_MODE
和
EXTRA_PREVIOUS_SCAN_MODE
,
分别提供新旧扫描模式。各选项的可能值
extra 如下所示:
SCAN_MODE_CONNECTABLE_DISCOVERABLE
- 设备处于可检测到模式。
SCAN_MODE_CONNECTABLE
- 设备未处于可检测到模式,但仍然可以接收连接。
SCAN_MODE_NONE
- 设备未处于可检测到模式,无法接收连接。
如果您要发起与远程设备的连接,则无需 启用设备可检测性。只有在以下情况下,才需要启用可检测性 您希望应用托管一个用于接受传入消息的服务器套接字 因为远程设备必须能够发现其他设备 发起与这些其他设备的连接