6

Trying to get my app to use less power, it's tracking location always in the background but I'd like for it automatically pause so I can turn on region watching and use that to resume precise location monitoring once the user moves around a bit.

I've had the app on for half an hour now and the location service is not pausing. I think this has been the case since Apple changed location stuff in iOS 13? I'm not really sure. All the documentation I can find online seems extremely outdated.

Any advice is greatly appreciated, relevant code follows:

init() {
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = 10
        locationManager.activityType = .fitness
        locationManager.requestAlwaysAuthorization()
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = true
        locationManager.showsBackgroundLocationIndicator = true
        locationManager.startUpdatingLocation()
    }
    func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager) {
        delegate?.paused(tracker: self)
        print("MT | LOCATION SERVICES PAUSED!") <---- NEVER GETTING CALLED (been running for 40 minutes now, no location updates, still going though?)
        // if not already, start region monitoring

    }
 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        // Collect data
        for location in locations {
           print("MT | New Location: \(location)")
        }
    }
nickneedsaname
  • 731
  • 1
  • 5
  • 22
  • Are you connected to Xcode? – mfaani Feb 07 '20 at 19:28
  • Also are you seeing different behavior with iOS12? – mfaani Feb 10 '20 at 14:48
  • I am connected to XCode, iirc it was properly pausing in iOS 12. It might've been 11? I'm 90% positive there was a point in time where it was pausing properly and doesn't seem to be anymore. Even with GPS jitter and inaccuracy and such I feel the expectation that it knows to pause when I got to sleep for 8 hours and leave my phone next to my bed is not unreasonable – nickneedsaname Feb 10 '20 at 16:20
  • 1
    Try to reproduce it on different devices and see if it differs. There is no documentation (that I know of) on exactly how the pause is triggered. – Krumelur Feb 11 '20 at 01:19
  • _iirc it was properly pausing in iOS 12._ Can you test it again? I want us to avoid speculation as much as we can – mfaani Feb 11 '20 at 03:27
  • How can I test it again on iOS 12 on a device? I don't have an iOS 12 device anymore... I would love to test it on iOS 12 and 11! I agree that would help narrow down possible causes. – nickneedsaname Feb 11 '20 at 18:45
  • Region watching to turn back on location updates won’t work. Resuming location updates requires user interaction. See my answer. – Krumelur Feb 11 '20 at 20:15

4 Answers4

1

I wouldn't rely on connecting to Xcode. Xcode is generally greedy. It doesn't want you to stop your debugging. So it never puts the app in a suspended state.

The callback of locationManagerDidPauseLocationUpdates is somewhat identical to your app being suspended which Xcode prevents.

The way I would test this is to use os.log. Then log the outputs to your Mac's console app. See here.


Just make sure the app is not launched from you running from Xcode. I'd rather disconnect your device from Xcode, kill the app. Disconnect your device from Xcode. Then just tap on the app icon again. That way Xcode cannot intervene.

mfaani
  • 33,269
  • 19
  • 164
  • 293
  • Good suggestion! Part of the reason I'm trying to fix this is if I leave the app on overnight it's killing my battery. I'll try this out but I'm pretty sure this isn't the issue. – nickneedsaname Feb 08 '20 at 01:05
  • Other than location tracking do you have any other background operation? – mfaani Feb 08 '20 at 02:15
  • I previously had a websocket open, but that reaaallllllllllyyyyyyy nukes the battery so I stopped that (and you can see that from xcode energy logs) – nickneedsaname Feb 10 '20 at 16:22
  • so what happened when you disconnected from Xcode and launched it? Did you use os_log to see what's going on? – mfaani Feb 10 '20 at 16:28
  • That should be fairly straightforward. But to get to know all you've done on that, it might just be better to post that issue in a separate question. Just share the link here... – mfaani Feb 11 '20 at 14:56
  • Good news: Figured out the logging issue - debug logs aren't flushed w/o a configuration change. Switched to default logs and I see them now. Bad news: This isn't the issue, or there needs to be >30m of inactivity before location stuff turns itself off. – nickneedsaname Feb 11 '20 at 18:34
  • I'm confused. Does it turn off after 30mins? – mfaani Feb 11 '20 at 18:35
  • Maybe? We'll see in about 20 minutes, I suspect it won't. – nickneedsaname Feb 11 '20 at 18:41
  • Ok. Please be more clear in your comments. Idk if I was to get to the bottom of them, I'd spin up a brand new project. A project that has nothing but a simple core-location. Test it on different iOS versions and give it a good hour to see if you get that log. You can create a distinct log so the moment you get pause, you'll see it in console. Also just to be sure. **Did you disconnect from Xcode, kill the app, launch it again and then connect to console?** – mfaani Feb 11 '20 at 18:46
  • I built/installed/ran the project from xcode, killed the app, killed xcode, restarted the app, and then started console.app I'll try a basic project with nothing but core location – nickneedsaname Feb 11 '20 at 18:49
  • Basic project doing nothing but tracking location does not pause after 18 minutes. I bumped my phone a bit and it started tracking locations again, I'll update again at 30m. I suspect it's still not going to work. – nickneedsaname Feb 13 '20 at 21:14
  • try on a previous iOS version as well. Can you also make sure that location tracking is disabled for other apps? – mfaani Feb 13 '20 at 21:16
  • @nickneedsaname I'm a bit spitballing at this point, but try one more thing. Try setting the authorization `requestWhenInUseAuthorization `. Delete the app and test it again – mfaani Feb 13 '20 at 21:19
  • I appreciate the spitballing! How do I test on previous iOS version? I only have my phone to test on and I don't know how to downgrade iOS versions :( – nickneedsaname Feb 13 '20 at 21:28
  • @nickneedsaname You can't downgrade. Don't waste time on that. But at least try with a different authorization as well. Also if you can share your entire code with all code that does the logging, I'd be happy to try it and connect to console and test it and take a look in the upcoming days... – mfaani Feb 13 '20 at 21:29
  • Still not working :( What's the best way to get you code? – nickneedsaname Feb 13 '20 at 23:23
  • Can you bring it to my home? :) GitHub – mfaani Feb 13 '20 at 23:26
  • https://gist.github.com/NickNeedsAName/730941835d29a1e39326561e4b7a85d6 Obviously this isn't everything - create a new project in xcode. Add the required "Privacy - Location..." keys + descriptions in your Info.plist, add tracker.swift from the gist, and then copy/paste over your appDelegate with the one in the gist. Also be sure to enable background location updates in the capabilities section of your .project(or w/e the extension on the blue thing is) file – nickneedsaname Feb 14 '20 at 19:09
  • Confused. Why didn’t you just upload the entire mini project in Xcode? That way I can be sure we’re working on the same thing... – mfaani Feb 14 '20 at 20:29
0

The issue is caused by your desired accuracy.

You are setting the accuracy to the best, which will make your application run continuously, so it will never pause in any iOS versions.

Furthermore, in a practical test whether it is pausing or not, change the accuracy to kCLLocationAccuracyHundredMeters. It will definitely pause. You can change the filter accuracy as you need for the next update.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • I will try it, thanks. I don't think this is it though. – nickneedsaname Feb 14 '20 at 19:06
  • Ya this doesn't fix things :\ – nickneedsaname Feb 14 '20 at 19:53
  • 1
    Please take the time to spell words completely ("bcoz" -> "because"), to use proper capitalization ("ios" -> "IOS") and formatting: "[How do I format my posts...](https://stackoverflow.com/help/formatting)". SO is not a message board or forum, it's more like an online reference book where those things matter. – the Tin Man Feb 14 '20 at 21:20
  • @nickneedsaname Similar to what Raghvendra said, your comments were never clear. I always had follow your comment with another question. Being crystal clear helps us to not make assumptions about your code or what you mean. But interestingly in my tests 2 years ago where it was pausing, I was actually testing it with `kCLLocationAccuracyHundredMeters` so Raghvendra's point is an interesting one. I just don't know based on what he's saying that. @ Raghvendra can you please explain? – mfaani Feb 14 '20 at 22:26
  • @Honey so what my point is pause will trigger when corelocation manager achieved the desired accuracy. In case of best accuracy with activity type fitness it will always try to get better accuracy again and again so it never(in most area in world) went to pause location delegate. – Raghvendra srivastava Feb 17 '20 at 05:25
0

Do you think maybe your activityType is preventing the location services to pause?

activityType

The location manager uses the information in this property as a cue to determine when location updates may be automatically paused. Pausing updates gives the system the opportunity to save power in situations where the user's location is not likely to be changing.

.fitness

This activity might cause location updates to be paused only when the user does not move a significant distance over a period of time.


I don't know what your particular use case is but, have you considered using the following function for background location tracking?

startMonitoringSignificantLocationChanges()

You may also try a mix of both, turning on significant location changes for day to day use and allowsBackgroundLocation when doing something like tracking a run, etc.

ohr
  • 1,717
  • 14
  • 15
  • I have tried all activity types for ~30 minutes each, no such luck. – nickneedsaname Feb 20 '20 at 18:56
  • @nickneedsaname I had a similar case where allowsBackgroundLocationUpdates kept the app running continuously in the background and consuming a large amount of energy throughout the day. Is there a particular reason why you need background location updates EVERY time your location manager is initialized? I feel like this should be a conscious decision to tun it on/off – ohr Mar 03 '20 at 19:54
-1

I think it is quite clear from the docs that this the pause functionality does not work like that. First of all, there is no guarantee that the GPS hardware will pause at all, it depends on the type of activity as well as other activities in the system. It is up to iOS to decide when and if to pause location updates, the property is just a hint.

More important, your use case would not work since if it gets paused, the user would have to interact with your app manually to resume updates.

Apple mentions your case specifically and recommends reducing the accuracy of location updates so it is only using cell tower triangulation instead of GPS (see docs above).

So, instead of using pausesLocationUpdatesAutomatically = true, you could do desiredAccuracy = kCLLocationAccuracyThreeKilometers.

To quote Apple,

[...] consider disabling this property and changing location accuracy to kCLLocationAccuracyThreeKilometers when your app moves to the background. Doing so allows you to continue receiving location updates in a power-friendly manner

Doesn't this cover your use case?

Krumelur
  • 31,081
  • 7
  • 77
  • 119
  • 1
    so what effect do you expect setting `pausesLocationUpdatesAutomatically` to `true` would have? – mfaani Feb 07 '20 at 19:53
  • Depending on factors outside your control, it *may* pause location updates. To resume location updates after this, the user needs to interact with your app. – Krumelur Feb 08 '20 at 09:19
  • 1
    In my tests from 2 years ago, it was pausing at approximately 17-18 minutes all the time. Because of other apps, GPS may not be stopped at the OS level, but for sure that app was being suspended... – mfaani Feb 09 '20 at 23:11
  • I believe you, but that doesn’t mean that it’s guaranteed. This may or may not change with OS versions, GPS use in other apps, etc, etc. Anyway Apple has the advice I quoted to the original problem, so I don’t see why this answer was downvoted. Even if it is not the accepted answer I believe it is a useful one. – Krumelur Feb 11 '20 at 01:17
  • 1
    I'm sorry I disagree with you. Not that Apple docs are the best but I've tested this a few times. Have you tried staying at a location for more than 17 minutes to see if it has been triggered? Or that's just your interpretation of the docs? I do agree that whatever we do the OS is above and beyond, but setting this property has enough of an effect to cause app go into a suspended state. Along with my tests the docs says **When this property is set to YES, the location manager pauses updates (and powers down the appropriate hardware) at times when the location data is unlikely to change.**. – mfaani Feb 11 '20 at 03:21
  • The only reason they have worded the next sentence with 'might' is because they don't want to give away the number of minutes you have to wait to cause it to pause. I suppose that can change or having a different activityType can cause the timing differently. – mfaani Feb 11 '20 at 03:21
  • @Honey if you poke around in the documentation I'm pretty sure it says the only thing that activityType is used for is for determining how long to idle before turning off location services. Overall I was about to quote exactly the line you just bolded, it explicitly says it will power down when the location data is unlikely to change. I'd say 3+ hours of no calls to the delegate that there are new locations indicates that location data is unlikely to change! – nickneedsaname Feb 11 '20 at 18:43
  • https://developer.apple.com/documentation/corelocation/cllocationmanager/1620567-activitytype "The location manager uses the information in this property as a cue to determine when location updates may be automatically paused." – nickneedsaname Feb 11 '20 at 18:45
  • 1
    @Honey No, I’ve never experienced the issue described in the question, and to me it usually suspends. I was just pointing out in my answer that there are actually no guarantees and there might be a better way to solve the original problem than relying on undocumented behavior. – Krumelur Feb 11 '20 at 20:13