想要在后台模式 iOS Swift 中运行广告外设

Nik*_*ack 1 background ads ios bluetooth-lowenergy swift

我只是用 Service & Characteristic UUID 创建我的广告外围设备

这是我的服务和特征 UUID

let kTRANSFER_SERVICE_UUID                = “29ada058-c7d6-4ed5-bc7f-1c7b0458b3b8”                                   
let kTRANSFER_CHARACTERISTIC_UUID = “91e032f2-c915-47c6-a8d9-6b3bc6c8e73d”
Run Code Online (Sandbox Code Playgroud)

现在我创建 CBPeripheralManager 的实例

private var peripheralManager: CBPeripheralManager!
private let beaconOperationsQueue = DispatchQueue(label: "beacon_operations_queue")
private let option = [CBCentralManagerScanOptionAllowDuplicatesKey:true]

// Assign peripheralManager with Queue & Option
peripheralManager = CBPeripheralManager(delegate: self, queue: beaconOperationsQueue, options: option)
Run Code Online (Sandbox Code Playgroud)

然后我调用这个 StartAdvertising 方法,但这只能在前台模式下工作,现在我想在后台模式下允许我在 Info.plist 中添加 UIBackgroundModes 键

 public func startAdvertising(serviceID: String, name: String) {

        let valueData = name.data(using: .utf8)

        self.serviceID = CBUUID(string: serviceID)
        self.peripheralName = name

        let CustomChar = CBMutableCharacteristic(type: CBUUID(string: kTRANSFER_CHARACTERISTIC_UUID), properties: [.read], value: valueData, permissions: [.readable])

        let myService = CBMutableService(type: self.serviceID, primary: true)
        myService.characteristics = [CustomChar]

        peripheralManager.add(myService)

        if self.peripheralManager.isAdvertising{

            self.peripheralManager.stopAdvertising()
        }
        peripheralManager.startAdvertising([
            CBAdvertisementDataServiceUUIDsKey: [serviceID],
            CBAdvertisementDataOverflowServiceUUIDsKey:[serviceID],
            CBAdvertisementDataLocalNameKey: peripheralName!])
    }
Run Code Online (Sandbox Code Playgroud)

所以当移动到后台时会发生这种情况

CBAdvertisementDataLocalNameKey 广告键被忽略,并且不会广告外设的本地名称。

CBAdvertisementDataServiceUUIDsKey 广告键的值中包含的所有服务 UUID 都放在一个特殊的“溢出”区域;它们只能被明确扫描它们的 iOS 设备发现。

我也被设置为“OverFlow”但仍然无法在后台模式下工作,

任何人都可以指导相同的

dav*_*ung 5

当应用程序在后台时,Apple 对 CoreBluetooth 广告和扫描的工作方式施加了限制。不幸的是,这种行为很复杂。请多多包涵。

出于本讨论的目的,背景是指应用程序在屏幕上不可见的任何情况。(手机锁定、屏幕关闭、显示跳板、显示另一个应用程序都是应用程序在后台的情况。)

CBPeripheralManager GATT 服务广告

  • 在后台,服务广告更改为 Apple 专有格式,该格式使用如下所示的制造商广告: 0b ff 4c 00 10 06 57 1e fc 8a e1 7c. 无论是在前台启动广告并将应用程序移至后台,还是在后台启动广告都没有关系。当广告 BLE 应用程序在后台时,此广告使用此专有格式。
  • 上述广告不包含服务 UUID。不管里面是什么CBAdvertisementDataServiceUUIDsKey,它都不会出现在广告中。
  • 上述广告不包含本地名称。不管里面是什么CBAdvertisementDataLocalNameKey,它都不会出现在广告中。
  • 此广告用于将指定的服务 UUIDCBAdvertisementDataServiceUUIDsKey仅从其他 iOS 设备通过前台应用程序扫描与CBCentralManager. 这使用 Apple 专有技术。实际的服务 UUIDS 仅在存在前台 iOS 应用扫描时,应操作系统的请求在“溢出区域”中由 iOS 提供。 如果没有前台 iOS 应用程序扫描,这将不起作用,因为永远不会从“溢出区域”请求实际服务 UUID。

CBCentralManager GATT 服务扫描

  • 在后台,不指定服务 UUID 的扫描不会产生任何结果。如果您有这样的代码:centralManager?.scanForPeripherals(withServices: nil, options: nil),则不会匹配。您必须明确指定服务 UUID。

  • 尝试从同一设备请求多个广告的回调将一无所获,因为该CBCentralManagerScanOptionAllowDuplicatesKey选项在后台被忽略。设备第一次出现时,您只会收到一个回调。

  • 根据上述限制,扫描特定服务 UUID 最多只能进行一次回调,前提是广告设备不是后台 iOS 应用程序。

  • 如果广告设备是后台 iOS 应用程序,则广告将使用上述专有技术。因为central在后台,所以iOS不会向后台的外设请求溢出区域。不会发生发现回调。

那么最终的结果是,只有当两个蓝牙应用程序之一在前台时iOS 到 iOS GATT 广告和发现才有效。如果两个应用程序都在后台,则新发现将不起作用。但是,当两个应用程序都在后台时,现有连接将继续工作并重新连接,如果设备消失并重新出现,将提供新的发现回调。关键是当两个应用程序之一在前台时,发现必须成功一次。

要使上述工作正常运行,您无需CBAdvertisementDataOverflowServiceUUIDsKey在开始广告时设置。CBAdvertisementDataServiceUUIDsKey如果广告应用程序在后台,Apple 会自动将键的任何值放入溢出区域。该CBAdvertisementDataOverflowServiceUUIDsKey是只读-你可以在接收到扫描结果访问这些信息。做广告时不要使用它。

有趣的注意事项:在这种情况下,当您有两个以上的 iOS 设备时,如果有第三个 iOS 应用程序扫描作为前台的中央设备,则中央设备和外围设备可以在两者都在后台时发现彼此。然后,第三个 iOS 设备可以发出“溢出区域”的请求,允许后台 iOS 设备侦听并通过窃听受益。

Android 或其他非 iOS 设备可以扫描上述专有的 iOS 广告,虽然它们看不到 Service UUID 或从“溢出区域”请求它们,但它们仍然可以连接,然后在连接内查询服务 UUID。这是低效的,但它可以工作。