经典蓝牙学习记录
Android app 可通过Bluetooth API 执行以下操作:
- 扫描其他蓝牙设备
- 查询本地蓝牙适配器的配对蓝牙设备
- 建立 RFCOMM 通道
- 通过服务发现连接到其他设备
- 与其他设备进行双向数据传输
- 管理多个连接
蓝牙进行通信的四大 必需任务 :
设置蓝牙、查找局部区域内的配对设备或可用设备、连接设备、在设备之间传输数据
基础知识:
- A、B 通过 配对 过程形成通信通道
- 设备 A 设置为可接收传入的连接请求
设备 B(发起配对请求的设备)使用 服务发现 过程找到 A(可检测到的设备) - 在 A(可检测到的设备)接受 B的 配对请求 后, A、B 完成 绑定 过程,并在此期间交换安全密钥
- A、B 会缓存这些密钥,以供日后使用。
- 完成配对和绑定过程后,A、B会交换信息。
- 会话完成,B(发起配对请求的设备)会发起请求,释放与A的连接通道。两个设备会保留彼此绑定的状态,这样,只要他们均未删除彼此的邦迪,又都在彼此范围内就会自动连接。
申明权限:
<manifest>
<!-- (老设备不需要)需要查找其他蓝牙设备,如 BLE设备等 -->
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<!-- (老设备不需要)需要被其他蓝牙设备找到 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<!-- Needed only if your app looks for Bluetooth devices.
If your app doesn't use Bluetooth scan results to derive physical
location information, you can strongly assert that your app
doesn't derive physical location. -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!-- Needed only if your app makes the device discoverable to Bluetooth
devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<!-- Needed only if your app communicates with already-paired Bluetooth
devices. -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
...
</manifest>
设置蓝牙
权限允许后,借助 BluetoothAdapter,分两步完成蓝牙设置
-
获取
BluetoothAdapter
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // 设备可能不支持蓝牙 }
-
启用蓝牙
启动蓝牙对话框if (!bluetoothAdapter.isEnabled()) { // 检查是否已启动蓝牙 //未启动蓝牙,发出请求,通过系统设置启动蓝牙(只弹框,不会离开应用) Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
查找设备
使用 BluetoothAdapter
,通过 设备搜索 或 查询配对设备的列表 来查找远程蓝牙设备
设备搜索 是一个 扫描 过程。
A nearby Bluetooth device responds to a discovery request only if it is currently accepting information requests by being discoverable.
发现中文的文档描述不准确,就放英文的文档了。
局部区域内的蓝牙设备仅在其当前已启用可检测性时才会响应发现请求
设备启用可检测性
弹框(官方推荐)
int requestCode = 1;
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivityForResult(discoverableIntent, requestCode);
启用可检测性对话框
无感知方法:
public void setDiscoverableTimeout(int timeout) {
BluetoothAdapter adapter=BluetoothAdapter.getDefaultAdapter();
try {
Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);
setDiscoverableTimeout.setAccessible(true);
Method setScanMode =BluetoothAdapter.class.getMethod("setScanMode", int.class,int.class);
setScanMode.setAccessible(true);
setDiscoverableTimeout.invoke(adapter, timeout);
setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,timeout);
} catch (Exception e) {
e.printStackTrace();
}
}
网友评论