I've got an app that requires continuous GPS updates even when in the background. I've called startUpdatingLocation and have "App registers for location updates" set and I get fixes for about 15 minutes and then the application just stops getting updates.
What am I missing here?
Did you try to set :
myLocationManager.pausesLocationUpdatesAutomatically = NO;
The default value for this property is YES.
This helped for me, I had your same problem.
I think I figured it out. On iOS6 in order to save power you stop getting location updates because you are not moving.
locationManagerDidPauseLocationUpdates fires when this occurs.
Did you set the locationManager’s delegate? It was suggested here.
Also: perhaps it is dropping down to a lower accuracy after 15 minute, and giving you notifications of only large changes. Go for a drive, or set distant locations in the simulator, and see if you get updates then.
Related
I do not understand, I set PausesLocationUpdatesAutomatically to true, don't move the phone and after I call startUpdatingLocation the locationmanager never pause :( what did I miss ?
AllowsBackgroundLocationUpdates = true;
PausesLocationUpdatesAutomatically = true;
requestAlwaysAuthorization
startUpdatingLocation
I continuously receive DidUpdateLocations but no DidPauseLocationUpdates
Try to set activityType of your CLLocationManager to automotiveNavigation. Default other is set
How long did you wait? I had a similar case for when my authorizationStatus was set to requestWhenInUseAuthorization I was working for and it took roughly 16-17 minutes for it to pause. During that time even if the phone was sitting on my desk I was usually still getting updates sent to my didUpdateLocation method. If I remember correctly upon putting the app into background I was getting 2 location updates at the first few seconds I placed it the background and then like two updates at minute 1, another two updates at minute 5, another two at minute 10, another two at minute 14 and eventually another two before 17 and then the pause would happen. I guess the app is receiving the callbacks which check to 'make sure you've actually paused'
Though I didn't set the activityType to automotiveNavigation. I'm assuming setting to that will reduce the time it takes to find out it has to fire the locationManagerDidPauseLocationUpdates callback.
Additionally the callback you will get is locationManagerDidPauseLocationUpdates this. You said DidPauseLocationUpdates but I'm guessing you're talking about the same thing...
If I start my application in airplane mode, I am expecting my delegate location manager object to have a fail since it should ben unreachable.
However, the method "locationManager:didUpdateLocations" gets called instead, and a location is given, but appears to have some internal objects to "nil".
The whole thing brings a consequent crash when the location object is passed and used.
Shouldn't I receive a fixe error if the device is in airplane mode, with the method "locationManager:didFailWithError:" being invoked?
This doesn't happen if the app is already working.
FYI, in devices running iOS 8.3 or greater, GPS is not disabled when airplane mode is enabled.
Just for whoever will be asking the same question (that can be found elsewere here on stackoverflow asked in different ways), The CLLocationManager has an internal cache that expires after a bit.
This means that if you go on Airplane mode and ask for a location, the location manager sends you the most recent it fixed UNTIL it clears the cache after a few minutes (almost 30), then it gives a location error.
Mi crash was because of something else, so the object returned works just fine.
If you want to be sure the fix has been done exactly when you asked for it, there's a "timestamp" property on a cllocation object that could be compared with [NSDate date] to understand if the returned location is "fresh" or cached.
My CLLocationManager starts when the user first enters the app. I am initializing it like this:
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = kDistanceFilter;
self.locationManager.headingFilter = kHeadingFilter;
And I am using geofencing.
I have defined in my .plist the required background modes.
If I test the app in the simulator using a gpx file, it works fine. So far, so good.
However, I read in these two links:
Start Location Manager in iOS 7 from background task
Background Location Services not working in iOS 7
That in iOS7, when the location does not change for a couple of minutes then the CLLocation goes to sleep.
My question is that:
I do not call didUpdateLocation at all, I only want the didEnterRegion, or didExitRegion. Theoretically, will it work , even the app is killed or user Location has not changed in the last hour and then decides to move?
There are a few elements in your questions:
1- In order not to rehash what is in a previous answer, I would first look at my answer at this link. It will help you resolve around the core location updates stopping if the user stops moving and how you can modify that behaviour:
iOS7 Core Location not updating
2- If the user kills an app in iOS7 (by flicking it up in the app switcher), the app will not restart and as such neither your location updates nor region monitoring will restart after the phone is restarted. On the other hand, if the app is killed because of memory pressures, iOS will restart the app and relaunch your location updates and region monitoring in the background. Also, if you reboot the phone, region monitoring will restart automatically. You obviously must have the background mode enabled.
3- Now you are talking about regions in your questions so I am assuming you have implemented CLCircularRegion. If not, that should be the first step and then "startMonitoringForRegion". In your case, even if the user has stopped moving for a while and then started moving, the app will be awaken/delegate called when the app enters or exit a region.
4- Make sure to use locationManager: didDetermineState: forRegion: as well. This will allow the app to determine if it is inside or outside of the region at start. This is useful when you think of an app being launched and no region crossing has happened but it is important to know whether the user is inside or outside of the region.
Hope this helps
I have been doing some reading about CLBeaconRegion and I have setup some iBeacons successfully and had it trigger location updates, even while the application is in the background.
However, from what I've read and carry over from CLRegion, I understand that it should be possible to hit locationManager:didEnterRegion: after the application is terminated.
I've setup my CLBeaconRegion like this:
beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:SERVICE_UUID]
major:0
minor:0
identifier:BEACON_ID];
[beaconRegion setNotifyOnEntry:YES];
[beaconRegion setNotifyOnExit:YES];
[beaconRegion setNotifyEntryStateOnDisplay:YES];
But I am not able to trigger the CLLocationManager's delegate from termination. I've left the region (confirmed by a notification), travelled further away from the beacon, waited for 30 seconds, then travelled back to the beacon, but it does not trigger the delegate while terminated (works great while in the background and foreground).
Should this work from termination? Am I missing something? Any help would be great.
I believe that when you are in the background or not running, it calls locationManager:didDetermineState:forRegion: instead of locationManager:didEnterRegion:, and then only if you've set notifyEntryStateOnDisplay to TRUE.
This is the expected behavior on iOS 7. However, this behavior has been changed under iOS 7.1. iOS 7.1 reverts delegate calls back to pre-iOS 7 behavior.
I've documented this behavior in a blog post of mine.
http://www.simplymadeapps.com/blog/2014/03/7-1-brings-back-geofence-behavior/
EDIT: The below is no longer true as of 7.1. You can still receive notifications even when the application has closed
The behavior of applications being swiped away in the application switcher now has the effect you're describing under iOS 7.
Users who remove your application from the switcher have made a decision to not allow your app to run in the background. Thus, region monitoring will not re-open your application.
Check out the "What’s New with Multitasking" session from WWDC 2013 for more information.
Yeah,
Same behaviour is being noticed .Sometimes even while calling setNotifyEntryStateOnDisplay, didEnterRegion not called even when in foreground.
I have searched far and wide for documentation on how to record audio in the background and have come to the conclusion that specifying 'audio' in the plist file might work. But, because iOS 4 will terminate background apps when it runs low on memory, we must also take some steps to reduce our memory usage when we transition to the background. How do we reduce our memory usage?
Also, does anybody know a sure shot way of recording audio in the background on iOS??
I unchecked the box in the Info.plist file that says "Application does not run in background" and also added the
<key> UIBackgroundModes </ key> < array> < string> audio</ string></ array>
in Info.plist. But, the recording stops as soon as I press the "HOME" button.
What callbacks do we implement to know that application has gone to background?
Please advise.
Just in case anyone else is looking for an answer here, I got mine working by adding the UIBackgroundModes array to the plist, adding 'audio' as Item 0.
I free up all memory/controllers on exit as you would by quitting the app anyhow so all that is left are the buffers the app uses (I've allocated around 1Mb though which makes me a little nervous however it seems to have worked!) I guess reducing the fidelity would help too but it seems to work as is.
In my core Audio setup I had to either change the buffer size from 1024 to 4096 or explicitly set the buffer size... I opted for the latter as latency was an issue.
NSTimeInterval iobuffersize = (float)1024.0f/SAMPLE_RATE);
sizeofdata = sizeof(iobuffersize);
AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, &sizeofdata, &iobuffersize);
I also had to make sure that it didn't kill the app on exit via not enabling the 'Does not run in background' option however this should be off by default anyhow.
So guess I'm answering this for peace of mind for anyone else that it does work with not much setup after all.
I am however experiencing problems with Bluetooth setup, I guess that's because the buffer sizes change again but can't figure this one out... just get -50 = invalid property warning when rendering the data via the recordingCallback. I'm guessing it's the freq/sample size but who knows... will look later but seems like background now works.
Apart from specifying background recording in the plist file, we can implement applicationDidEnterBackground wihch will tell us when the application enters background. Here, we should stop any updates to the UI because that consumes memory for eg, updating a timer and an equalizer.
The call applicationWillEnterForeground will be called just before the app returns to foreground so we can resume whatever we stopped.
The recording then takes place in the background. It would also help to implement an interruption listener(this would work in the backgroud as well) so that you don't lose your recordings.