Hello
I'm building an indoor geofencing app with iBeacons. I want to detect each time a user approaches a beacon and the distance and save this data with Core Data only if the distance (proximity) to the iBeacon is close. I am using Core Location to do this but I am not using the didEnter / didExit functions as they do not provide the distance to the beacon. I am mainly using the didRange function from locationManager to get all the beacons, find the closest one and its distance.
This approach works perfectly while the app is in the foreground. However, the app starts not working properly in the background. If I just change the app, the didRange function stops working, but if I lock the phone and look at the time on the lock screen, it starts working. The problem is not that the app does not work in the background, but that the functions are activated only in specific cases or times, eg. the phone is locked.
I added these properties in the info.plist
- Privacy - Location When In Use Usage Description
- Privacy - Location Always and When In Use Usage Description
- Required background modes: Location updates
I also added this code:
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
This is how I add a beacon and start monitoring it:
func addBeacon(id: String, major: Int16 = 0, minor: Int16 = 0) {
guard let uuid = UUID(uuidString: id) else { return }
let region = CLBeaconRegion(uuid: uuid, major: CLBeaconMajorValue(major), minor: CLBeaconMinorValue(minor), identifier: id + major.description + minor.description)
region.notifyOnEntry = true
region.notifyOnExit = true
region.notifyEntryStateOnDisplay = true
self.locationManager.startMonitoring(for: region)
resetValues()
}
func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
let beaconRegion = region as! CLBeaconRegion
if state == .inside {
// Start ranging when inside a region.
manager.startRangingBeacons(satisfying: beaconRegion.beaconIdentityConstraint)
} else {
// Stop ranging when not inside a region.
manager.stopRangingBeacons(satisfying: beaconRegion.beaconIdentityConstraint)
}
}
I am also making sure that locationManager.requestAlwaysAuthorization()
is always true
Do you have any ideas why it is not always working in the background?
Thanks for your time.