前一篇文章介绍了蓝牙的基础知识。今天就说下具体实践。
说起蓝牙开发,听起来高大上,其实就像“手机和外设谈恋爱”,核心是:发现-连接-读写,掌握这一点,就能很好地开发了。
下面开始介绍
一、准备工作
- 导入Framework和设置蓝牙权限
在项目中导入CoreBluetooth
框架,并在Info.plist
中添加蓝牙权限描述:
NSBluetoothAlwaysUsageDescription
需要蓝牙权限连接设备 - 创建并初始化蓝牙管理器
创建一个BlueCentralManager
实例,管理本应用程序的蓝牙:
import Foundation
import CoreBluetooth
class BluetoothManager: NSObject {
var centralManager: CBCentralManager!
var connectedPeripheral: CBPeripheral? // 存储连接的外设
let myDeviceName = "xxxx"
let serviceUUID = CBUUID(string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
let characterUUID = CBUUID(string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
override init() {
super.init()
centralManager = CBCentralManager(delegate: self, queue: nil)
}
}
创建好实例后,就按蓝牙六个步骤进行操作。至于为什么是这样?我想这就是蓝牙开发的步骤,没有好说的。
二、蓝牙开发六步走
- 检查蓝牙状态
通过代理方法确定手机蓝牙是否可用:
extension BluetoothManager: CBCentralManagerDelegate {
//检查蓝牙状态
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
print(“蓝牙已开启,开始扫描设备”)
central.scanForPeripherals(withServices: nil, options: nil)
case .poweredOff:
print(“请打开蓝牙”)
default: break
}
}
}
注意这里需要在CBCentralManagerDelegate代理实现,后面的步骤也是如此
通过这一步确定了手机蓝牙可用后,就继续下一步 - 扫描外设
发现设备时,会触发didDiscover
回调。
这里可以显示蓝牙设备列表,也可以找我们固定想要找的蓝牙设备,本实例就实现后者。例如假设我们找名字为“MyDevice”的设备:
extension BluetoothManager: CBCentralManagerDelegate {
//扫描外设
func centralManager(_ central: CBCentralManager,
didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any],
rssi RSSI: NSNumber) {
if peripheral.name == myDeviceName {
print(“找到设备:(peripheral)”)
connectedPeripheral = peripheral
central.stopScan() // 停止扫描
central.connect(peripheral, options: nil) // 发起连接
}
}
} - 连接设备
连接成功后会触发didConnect
回调,此时要设置外设的代理:
extension BluetoothManager: CBCentralManagerDelegate {
//连接设备
func centralManager(_ central: CBCentralManager,
didConnect peripheral: CBPeripheral) {
print(“连接成功!”)
peripheral.delegate = self
peripheral.discoverServices(nil) // 开始搜索服务
}
}
在连接设备成功之后,就开始搜索服务.注意:
前面三步是使用CBCentralManagerDelegate代理,
后面的步骤就使用CBPeripheralDelegate代理.
- 发现服务与特征
对于一个外设来说,可能有多个服务(Service),而每个服务包含多个特征(Characteristic):
extension BluetoothManager: CBPeripheralDelegate {
// 发现服务
func peripheral(_ peripheral: CBPeripheral,
didDiscoverServices error: Error?) {
guard let services = peripheral.services else { return }
for service in services {
print(“发现服务:(service.uuid)”)
// 搜索该服务的所有特征
if service.uuid == serviceUUID {
peripheral.discoverCharacteristics(nil, for: service)
}
}
}
}
extension BluetoothManager: CBPeripheralDelegate {
// 发现特征
func peripheral(_ peripheral: CBPeripheral,
didDiscoverCharacteristicsFor service: CBService,
error: Error?) {
guard let characteristics = service.characteristics else { return }
for char in characteristics {
print(“特征UUID:(char.uuid)”)
if char.uuid == characterUUID {
let data = “Hello Buletooth”.data(using: .utf8)
sendData(characteristic: char, data: data!)
}
}
}
} - 读写数据
读取数据:直接调用readValue
写入数据:注意选择写入类型(withResponse
需对方确认)
extension BluetoothManager: CBPeripheralDelegate {
// 发送数据示例
func sendData(characteristic: CBCharacteristic, data: Data) {
guard let peripheral = connectedPeripheral else { return }peripheral.writeValue(data, for: characteristic, type: .withResponse)
} // 接收数据回调
func peripheral(_ peripheral: CBPeripheral,
didUpdateValueFor characteristic: CBCharacteristic,
error: Error?) {
if let data = characteristic.value {
let message = String(data: data, encoding: .utf8)
print(“收到数据:(message ?? “”)”)
}
}
} - 断开连接
extension BluetoothManager: CBPeripheralDelegate {
//断开连接
func disconnect() {
if let peripheral = connectedPeripheral {
centralManager.cancelPeripheralConnection(peripheral)
}
}
}
以上就是蓝牙连接的6个步骤,每一步像环一样,一环紧扣一环,环环相扣。
下面再讲下开发过程中的注意事项。
三、注意事项:
1.权限问题:iOS18要求蓝牙权限必须在Info.plist
中明确声明。
2.主线程问题:所有蓝牙回调默认在后台线程,更新UI记得切回主线程。
3.特征属性:写数据前检查特征的.properties
是否包含.write
。
以上就是蓝牙开发的整体流程。
其实做过之后,比较简单,按固定流程开发即可。最关键的是要自己去实践一把。
声明:来自程序员华仔,仅代表创作者观点。链接:https://eyangzhen.com/2035.html