My goal is to advertise a beacon in background mode.
The expected result is: The beacon continue to advertise in background mode.
The actual result is: The beacon stop advertising in background mode.
What I've tried:
- Background task can extend time for 30 seconds but this is not a solution.
import Foundation
import CoreLocation
import CoreBluetooth
protocol BeaconBroadcaster {
/// Broadcast to be find by scanner.
/// - Parameters:
/// - uuid: used by broadcast scanner to find specific uuid
/// - major and minor: used by broadcast scanner to differentiate beacon with identical uuid
func startBroadcasting(uuid: UUID, major: UInt16, minor: UInt16) -> BeaconBroadcasterStartBroadcastingEvent
/// stop broadcaster
func stopBroadcasting() -> BeaconBroadcasterStopBroadcastingEvent
}
class BeaconBroadcasterImpl: BeaconBroadcaster {
private var peripheralManager = CBPeripheralManager()
fileprivate init() {
#if DEBUG
print("\(type(of: self)) \(#function)")
#endif
}
func startBroadcasting(uuid: UUID, major: UInt16, minor: UInt16) -> BeaconBroadcasterStartBroadcastingEvent {
if peripheralManager.state == .poweredOff {
return .BLUETOOTH_NOT_ENABLED
}
if peripheralManager.state == .unauthorized {
return .BLUETOOTH_NOT_AUTHORIZED
}
if peripheralManager.state != .poweredOn {
return .BLUETOOTH_NOT_AUTHORIZED
}
if peripheralManager.isAdvertising {
_ = stopBroadcasting()
}
let bundleURL = Bundle.main.bundleIdentifier!
let constraint = CLBeaconIdentityConstraint(uuid: uuid, major: major, minor: minor)
let region = CLBeaconRegion(beaconIdentityConstraint: constraint, identifier: bundleURL)
let peripheralData = region.peripheralData(withMeasuredPower: nil) as? [String: Any]
peripheralManager.startAdvertising(peripheralData)
return .BROADCASTER_IS_STARTING
}
func stopBroadcasting() -> BeaconBroadcasterStopBroadcastingEvent {
if !peripheralManager.isAdvertising {
return .BROADCASTER_HAS_ALREADY_STOPPED
}
peripheralManager.stopAdvertising()
return .BROADCASTER_IS_STOPPING
}
}
extension BeaconBroadcasterImpl {
/// Usage: use force unwrap, it will always return non-nil value
static var shared: BeaconBroadcaster? {
get {
if sharedClosure == nil {
sharedClosure = BeaconBroadcasterImpl()
}
return sharedClosure
}
set {
sharedClosure = newValue
}
}
private static var sharedClosure: BeaconBroadcaster?
}