Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuous location update background iOS13

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.

like image 777
mattll Avatar asked Oct 09 '19 06:10

mattll


2 Answers

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.

enter image description here

like image 192
Prashant Tukadiya Avatar answered Sep 20 '22 12:09

Prashant Tukadiya


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.

like image 21
Amir Sagri Avatar answered Sep 18 '22 12:09

Amir Sagri