I created a beacon simulator app that advertises the beacon in foreground mode, the app runs in background mode but it does not advertise the beacon. Here is my working code
import UIKit
import CoreBluetooth
import CoreLocation
class ViewController: UIViewController,CBPeripheralManagerDelegate, CLLocationManagerDelegate {
@IBOutlet weak var major: UILabel!
@IBOutlet weak var minor: UILabel!
@IBOutlet weak var uuid: UILabel!
var locationManager: CLLocationManager!
var localBeacon: CLBeaconRegion!
var beaconPeripheralData: NSDictionary!
var peripheralManager: CBPeripheralManager!
let localBeaconUUID = "88b78a0c-34ae-44d0-b30c-001F12345620"
let localBeaconMajor: CLBeaconMajorValue = 58
let localBeaconMinor: CLBeaconMinorValue = 20
let identifier = "myBeacon"
let txPower = -40
var timer: Timer!
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
case .resetting:
print("central.state is .resetting")
case .unsupported:
print("central.state is .unsupported")
case .unauthorized:
print("central.state is .unauthorized")
case .poweredOff:
print("central.state is .poweredOff")
case .poweredOn:
print("central.state is .poweredOn")
peripheralManager.startAdvertising(beaconPeripheralData as? [String: Any] )
}
}
@objc func initLocalBeacon() {
if localBeacon != nil {
stopLocalBeacon()
}
let uuid = UUID(uuidString: localBeaconUUID)!
localBeacon = CLBeaconRegion(proximityUUID: uuid, major: localBeaconMajor, minor: localBeaconMinor, identifier: identifier)
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
beaconPeripheralData = localBeacon.peripheralData(withMeasuredPower:nil)
peripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)
}
func stopLocalBeacon() {
peripheralManager.stopAdvertising()
peripheralManager = nil
beaconPeripheralData = nil
localBeacon = nil
}
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
if peripheral.state == .poweredOn {
peripheralManager.startAdvertising(beaconPeripheralData as? [String: Any] )
}
else if peripheral.state == .poweredOff {
peripheralManager.stopAdvertising()
}
}
override func viewDidLoad() {
super.viewDidLoad()
major.text = "\(localBeaconMajor)"
minor.text = "\(localBeaconMinor)"
uuid.text = "\(localBeaconUUID)"
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(initLocalBeacon), userInfo: nil, repeats: true)
}
func peripheralManager(_ peripheral: CBPeripheralManager, willRestoreState dict: [String : Any]) {
if let services = dict[CBPeripheralManagerRestoredStateServicesKey] as? [CBMutableService],
let service = services.first {
peripheral.add(service)
}
}
func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
if let error = error {
print("Error advertising service: \(error.localizedDescription)")
return
}
let power = NSNumber(integerLiteral: -59)
beaconPeripheralData = localBeacon.peripheralData(withMeasuredPower: power)
peripheralManager.startAdvertising(beaconPeripheralData as! [String: Any])
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("background")
peripheralManager.stopAdvertising()
let backgroundTask = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.peripheralManager.startAdvertising([CBAdvertisementDataLocalNameKey: "YourDeviceName", CBAdvertisementDataServiceUUIDsKey: [self.uuid]])
UIApplication.shared.endBackgroundTask(backgroundTask)
}
}
func applicationWillEnterForeground(_ application: UIApplication) {
peripheralManager.stopAdvertising()
}
}
I tried using "CLLocationManager" allowsBackgroundLocationUpdates and in sign-in & capabilities added
- background mode and enables
- location updates
- uses Bluetooth LE accessory
- background fetch
- background processing
- Acts as a Bluetooth LE accessory
These are the methods I tried that work perfectly in the foreground. Are there any other methods to work the beacon app to work in background mode?