更新15/6-1-替代方法
根据Paulw的建议,我改变了策略,而不是发现外围设备,而是与外围设备连接,并且当外围设备或中央设备处于前台时,它都工作正常。在以下情况下会发生此问题:
1)我在代表呼叫上设置通知。
2)外围和中央都在背景中。
3)当我靠近它们时,我看不到任何代表呼叫。
4)一旦将外围设备或中央设备置于前台,我就接到didDiscover
的电话,即使我现在将应用程序都放在后台的两部手机中,一切也都可以正常工作。
简而言之,如果两个都处于后台状态,则中央不会发现外围设备。 这是这两部分的代码:
func startAsPeripheral() {
peripheralManager = CBPeripheralManager(delegate: self, queue: DispatchQueue.global(qos: .background))
}
func startAsCentral() {
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.global(qos: .background))
}
}
extension BluetoothManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
LogManager.shared.log(object: "Central state update")
LogManager.shared.log(object: central.state)
if central.state != .poweredOn {
LogManager.shared.log(object: "Central is not powered on")
} else {
LogManager.shared.log(object: "Central scanning for: " + self.serviceUUID.uuidString);
self.centralManager.scanForPeripherals(withServices: [self.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey : false])
}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
self.centralManager.stopScan()
self.peripheral = peripheral
self.peripheral.delegate = self
self.centralManager.connect(self.peripheral, options: nil)
let name = advertisementData[CBAdvertisementDataLocalNameKey] as? String
LogManager.shared.log(object: "Peripheral (" + (name ?? "unknown") + "): " + RSSI.stringValue)
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
if peripheral == self.peripheral {
LogManager.shared.log(object: "Connected.")
peripheral.discoverServices([serviceUUID])
}
}
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
if peripheral == self.peripheral {
LogManager.shared.log(object: "Disconnected")
self.peripheral = nil
LogManager.shared.log(object: "Central scanning for: " + self.serviceUUID.uuidString);
self.centralManager.scanForPeripherals(withServices: [self.serviceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: false])
}
}
}
extension BluetoothManager: CBPeripheralDelegate {
func peripheral( _ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
LogManager.shared.log(object: "Services: \(peripheral.services!)")
for service in peripheral.services! {
peripheral.discoverCharacteristics(nil, for: service)
}
}
func peripheral( _ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
LogManager.shared.log(object: "Characteristics: \(service.characteristics!)")
}
}
extension BluetoothManager: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
switch peripheral.state {
case .unknown:
LogManager.shared.log(object: "Bluetooth Device is UNKNOWN")
case .unsupported:
LogManager.shared.log(object: "Bluetooth Device is UNSUPPORTED")
case .unauthorized:
LogManager.shared.log(object: "Bluetooth Device is UNAUTHORIZED")
case .resetting:
LogManager.shared.log(object: "Bluetooth Device is RESETTING")
case .poweredOff:
LogManager.shared.log(object: "Bluetooth Device is POWERED OFF")
case .poweredOn:
LogManager.shared.log(object: "Bluetooth Device is POWERED ON")
let service = serviceUUID
let myService = CBMutableService(type: service, primary: true)
let writeCharacteristics = CBMutableCharacteristic(type: characteristricUUID, properties: .write, value: nil, permissions: .writeable)
myService.characteristics = [writeCharacteristics]
peripheralManager.add(myService)
peripheralManager.startAdvertising([CBAdvertisementDataLocalNameKey : "Spacedemic", CBAdvertisementDataServiceUUIDsKey : [service]])
LogManager.shared.log(object: "Started Advertising")
default:
LogManager.shared.log(object: "Unknown State")
}
}
}
原始问题
我有一个用于跟踪联系人的应用程序。我将其配置为既可以在中央也可以在外围使用,都应该在后台和前台工作。这是用于联系人跟踪的,因此在大多数情况下,用户不会将应用程序置于前台状态。无论在背景还是前景方面,广告都可以像我观察到的那样很好地工作。这里的问题是,当Central处于后台时,它有时仅进入didDiscover
一次,有时甚至从未进入。因此,如果外围设备在范围之内,我将无法从中央检测到RSSI,或者用户无法从中央移开。相反,在前台时,我会使用didDiscover
方法中的RSSI进行频繁更新。
我该如何解决?还是有一种解决方法来获得所需的结果?