Continuous location update background iOS13
Asked Answered
T

2

12

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.

Tito answered 9/10, 2019 at 6:44 Comment(4)
Hey did you get the solution for this?Lemkul
Well, as stated in my last comment, I could drastically increase the duration before the application gets moved to the suspended state, by reducing the resources consumed in the background. -> I removed the motion collection completely from the app. -> When shifting into background I decrease the accuracy and increase the distanceFilter for locations to get less events, I stop some tasks that are updating the UI, I downsample the collection of other data sources, I do no exports of my data in the background or other workload. So now i get around 3000 minutes in the background.Tito
can you help me with some code?Lemkul
In your AppDelegate.swift implement the func applicationDidEnterBackground(_ application: UIApplication) and func applicationDidEnterBackground(_ application: UIApplication) functions. In those functions access your CLLocationManager and set the properties distanceFilter, desiredAccuracy accordingly. I also downsample my timer that I use to write some some usage information (like the current battery status) and end a timer that I use to periodically update the main view or vice versa when the applicationDidBecomeActive method. I guess playing around and testing is the key.Tito
G
4

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

Garcon answered 9/10, 2019 at 7:38 Comment(9)
Did that solve your issue? I manually set the authorization level to always in -> Settings -> Privacy -> Location Services But that did not solve the issue.Tito
@mattll You can't do much on this, iOS will decide when to show a dialogue to user for always allowGarcon
But even after I set the always allow flag, the Application will terminate at some point. Does your app run continuously afterwards?Tito
It does not matter whether i set the "WhenInUsage" as CLAuthorizationStatus or "Allow Once". My application will get suspended after a while. So i was wondering if your application will also get suspended or if it will continuously update the location in the background after setting the "always allow" in the dialogue.Tito
@mattll I am using Radar SDK , So I really never checked thatGarcon
Thanks for the update. I already encountered that popup, and also you can set the always notifications in the iphone privacy settings, but this doesnt solve the problem above for me. On iOS 12 I didnt encounter any problems with continuous location tracking yet, whilest on iOS 13 the app gets suspended after a while.Tito
I have the same problem! I don’t understand if it’s equal set authorization from popup and from privacy settingPeriodate
Here are my observations after exploring the problem over some time. In short words: The less I do while being in the background, the longer I can record until suspension. I disabled most of the functionality that was executed in the background, so for now i only track the location/some usage information and store it using core data. Additionally, when the application goes into background mode, I change the distanceFilter and desiredAccuracy of the location manager. Now, I can track for around 3000 without getting suspended.Tito
did anyone got this solution ?Lemkul
K
1

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.

Kosel answered 24/8, 2020 at 3:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.