I am currently testing the background location mode in iOS 13, as I want to track the user´s location and motion (using the CMMotionManager) in the background. Therefore, I have my own (singleton) class handling the location tracking. I initialize the CLLocationManager in the following way:
func initializeLocationManager() -> CLLocationManager {
let manager = locationManager ?? CLLocationManager()
manager.delegate = self
manager.requestAlwaysAuthorization()
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
manager.distanceFilter = kCLDistanceFilterNone
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.activityType = .other
return manager
}
Then I start the following services:
func startLocationServices() {
// ...
locationManager.startUpdatingLocation()
locationManager.startMonitoringVisits()
locationManager.startMonitoringSignificantLocationChanges()
// ...
}
In addition, I implemented the CLLocationManagerDelegate-methods didChangeAuthorization(), didUpdateLocation().
In the info.plist-file I appended the following entries:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>...</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
In my ViewController, I call the startLocationServices. Currently, I set the app's authorization to track location data to ".authorizedAlways"
The location updates stop after approximately 60 - 130 minutes.
To solve the problem, I already added the didFinishLaunchingWithOptions-function, which triggers the location-updates again:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let launchOptions = launchOptions,
let isLocationKey = launchOptions[UIApplication.LaunchOptionsKey.location] as? Bool,
isLocationKey {
restartServices()
}
return true
}
When the app gets awoken using this function, I managed to get continuous data on some tests, but sometimes the app was suspended again after a few minutes.
Last, I also tried a timer that restarts the location tracking every 5 minutes, but this does not seem to affect the update-duration at all.
So my question is if there is a way of continuously receiving the location updates in the background, or is there some option I am missing?
Thanks in advance.
Edit: I tested the application on iOS 12 and it gets continuous updates in 5/5 tests. So I guess the problem is related to iOS 13.
Nothing is wrong with code !! , I have faced the same issue and after research I found that
At the WWDC19 keynote Apple announced two changes in the way location permissions will work in iOS 13. The first change gives users the option to share their location with your app just once. This makes it easier to try out location features and helps users keep sensitive location data private.
The first notable change is that even when you call requestAlwaysAuthorization
, the user will only get the ‘just now’ and ‘when in use’ options in the permission dialog. If the user grants you ‘when in use’ permission and you try to scan for location in the background, only then the user will be presented a dialog to grant the background permission.
So When user grants WhenInUseUsage permission You will get always
in CLAuthorizationStatus
and If user choose Allow Once
CLAuthorizationStatus
will be rested to notDetermined
once app launches again
You can check this article for detailed info https://medium.com/q42-engineering/apple-location-permission-ios13-1e0e59002889
And Here is video https://developer.apple.com/videos/play/wwdc2019/705/
EDIT
After When In User permission granted by the user iOS will show user a another dialogue after some days to change permission from when in use to always allow.
So now there is no way to directly ask user for always allow permission instantly like we do before.
This is an iOS 13 bug. The app permissions get messed up by iOS. While it shows "Always" in settings, it actually behaves more like "While in Use". One app is put to sleep in background while other keeps getting locations on the same device (in background).
To solve it, goto Settings-> Search your app with issue -> Location -> Change Always to Never and then back to Always.
Unfortunately, there is nothing, you can do in the code to fix this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With