在“背景模式”设置中,我启用了“使用Bluetooth LE附件”和“充当Bluetooth LE附件”,这些已添加到Info.plist中。并且我还允许我的应用访问“蓝牙共享”。
我的应用程序确实在前景模式下很好地扫描了BLE外设,,但是当它进入后台模式时,它不再扫描任何东西。如果再次进入前台模式,它的扫描效果会很好。
更具体地说,centralManagerDidUpdateState(_ central: CBCentralManager)
在任何模式下都能正常工作。但是didDiscover
在后台模式下不起作用。
我想BLE扫描在任何模式下都能正常工作,我想我已经尽力了。
BLEManager.swift
import UIKit
import CoreBluetooth
final class BLEManager: NSObject, CBCentralManagerDelegate, CBPeripheralManagerDelegate {
static let shared: BLEManager = .init()
var centralManager: CBCentralManager?
var peripheralManager: CBPeripheralManager?
var scannedPeripherals: [CBPeripheral] = .init()
var confirmedPeripheralStates: [String: CBPeripheralState] = .init()
override init() {
super.init()
self.centralManager = .init(delegate: self, queue: nil)
self.peripheralManager = .init(delegate: self, queue: nil)
}
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .poweredOn:
self.startScan()
default:
central.stopScan()
}
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
print("[BLE] state: \(peripheral.state.rawValue)")
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
self.scannedPeripherals.appendAsUnique(peripheral)
central.connect(peripheral)
self.confirm(peripheral)
}
func startScan() {
guard let central = self.centralManager else {
return
}
let isBackgroundMode: Bool = (UIApplication.shared.applicationState == .background)
let cbuuids: [CBUUID] = self.scannedPeripherals.map { CBUUID(nsuuid: $0.identifier) }
central.stopScan()
central.scanForPeripherals(withServices: isBackgroundMode ? cbuuids : nil)
}
func confirm(_ peripheral: CBPeripheral) {
let uuid: String = peripheral.identifier.uuidString
// Prevent duplicate logging.
if peripheral.state != self.confirmedPeripheralStates[uuid] {
self.log(peripheral)
}
self.confirmedPeripheralStates[uuid] = peripheral.state
}
func log(_ peripheral: CBPeripheral, completion: (() -> Void)? = nil) {
guard let name = peripheral.name,
let state = self.getPeripheralStateAsString(peripheral.state) else {
return
}
print("[BLE] \(name) was \(state) on \(self.getApplicationStateAsString())")
}
}
extension BLEManager {
func getApplicationStateAsString() -> String {
switch UIApplication.shared.applicationState {
case .active:
return "active"
case .inactive:
return "inactive"
case .background:
return "background"
}
}
func getPeripheralStateAsString(_ state: CBPeripheralState) -> String? {
switch state {
case .disconnected:
return "disconnected"
case .connecting:
return "connecting"
case .connected:
return "connected"
default:
return nil
}
}
}
extension Array where Element: Equatable {
mutating func appendAsUnique(_ element: Element) {
if let index = self.index(where: { $0 == element }) {
self.remove(at: index)
}
self.append(element)
}
}
AppDelegate.swift
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
BLEManager.shared.startScan()
}
我有什么想念吗?