You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

iOS无法通过Service UUID连接蓝牙设备并读写特征(Android正常)

iOS蓝牙连接问题排查方案

问题概述

iOS平台无法通过Service UUID 0000FD00-0000-1000-8000-00805F9B34FB 连接蓝牙设备,也无法读写特征 0000FD03-0000-1000-8000-00805F9B34FB,但同一设备在Android平台可正常连接传输。当前代码既无法检测到设备,也无报错信息。

相关UUID信息

  • Service UUID: 0000FD00-0000-1000-8000-00805F9B34FB
  • Read特征UUID: 0000FD03-0000-1000-8000-00805F9B34FB

当前使用代码

class BluetoothManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
    var centralManager: CBCentralManager!
    var peripheralDevice: CBPeripheral?
    var eSIMCharacteristic: CBCharacteristic?

    // UUIDs for the custom service and characteristic
    let eSIMServiceUUID = CBUUID(string: "0000FD00-0000-1000-8000-00805F9B34FB")

    override init() {
        super.init()
        // Initialize the CBCentralManager
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    // Central Manager state change (check if Bluetooth is available)
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        if central.state == .poweredOn {
            // Start scanning for the charging box
            centralManager.scanForPeripherals(withServices: [eSIMServiceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
        }
    }

    // Discovered a peripheral (charging box)
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        print("peripheral", peripheral, peripheral.identifier)
        // Stop scanning and connect to the peripheral
        centralManager.stopScan()
        peripheralDevice = peripheral
        peripheralDevice?.delegate = self
        centralManager.connect(peripheral, options: nil)
    }

    // Connected to the peripheral (charging box)
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        // Discover services on the peripheral
        print("Connected to device: \(peripheral.name ?? "Unknown")")
        peripheral.discoverServices([eSIMServiceUUID])
    }

    // Discovered services on the peripheral
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        print("error occured", error)
    }
}

排查与修复步骤

  • 先扫描所有设备,验证设备是否可被iOS发现
    iOS的scanForPeripherals(withServices:)仅会发现主动广播了对应Service UUID的设备,而Android允许扫描所有设备后再筛选。修改扫描代码,传nilwithServices

    centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
    

    如果能发现目标设备,说明设备没有广播FD00这个Service UUID,此时需要修改扫描逻辑:先扫所有设备,通过名称或identifier匹配后再连接,连接后再发现服务。

  • 补全关键代理方法,获取错误信息
    当前代码缺少多个核心回调,无法定位连接、扫描失败的原因,添加以下方法:

    // 连接失败回调
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        print("Failed to connect: \(error?.localizedDescription ?? "Unknown error")")
    }
    
    // 断开连接回调
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        print("Disconnected: \(error?.localizedDescription ?? "No error")")
    }
    
    // 服务发现后,遍历服务并发现特征
    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        if let error = error {
            print("Discover services error: \(error)")
            return
        }
        guard let services = peripheral.services else { return }
        for service in services {
            if service.uuid == eSIMServiceUUID {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }
    
    // 特征发现回调
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        if let error = error {
            print("Discover characteristics error: \(error)")
            return
        }
        guard let characteristics = service.characteristics else { return }
        for characteristic in characteristics {
            if characteristic.uuid == CBUUID(string: "0000FD03-0000-1000-8000-00805F9B34FB") {
                eSIMCharacteristic = characteristic
                // 读取特征值
                peripheral.readValue(for: characteristic)
            }
        }
    }
    
    // 特征值读取回调
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if let error = error {
            print("Read value error: \(error)")
            return
        }
        if let data = characteristic.value {
            print("Received data: \(data)")
        }
    }
    
  • 检查蓝牙权限配置
    Info.plist中添加蓝牙权限描述:

    • iOS 13及以上:添加NSBluetoothAlwaysUsageDescription(字符串类型,描述蓝牙使用场景)
    • iOS 12及以下:添加NSBluetoothPeripheralUsageDescription
      缺少权限会导致扫描静默失败,无任何回调。
  • 验证设备端UUID一致性
    确认设备端广播的Service UUID和代码中使用的完全一致,虽然CBUUID不区分大小写,但部分设备可能存在UUID格式差异(比如省略分隔符等),需和硬件端确认。

内容的提问来源于stack exchange,提问作者Mallikarjun C

火山引擎 最新活动