I'm doing a program who is looking for beacon, I implemented CLLocationManager and my apps works except one point.
I'm calling startMonitoringForRegion() in order to get the didEnterRegion/didExitRegion callback. Inside these function I'm doing startRangingBeaconsInRegion()/stopRangingBeaconsInRegion() in order to get precise information when the user is in the beacon area.
My issue is quite simple, if the app is started when the user is already in the beacon range, didEnterRegion is not called.
I'm looking for a function like isInRegion() so that when my app start I could do startMonitoringForRegion() then isInRegion() and startRangingBeaconsInRegion() if the user is already in the region.
My current workaround is to call startRangingBeaconsInRegion() when the app start, then in the didRangeBeacons callback, I'm doing stopRangingBeaconsInRegion() if no beacon is found.
I don't think that it's a very clean way and would like to replace by something better if possible
Thanks,
You can use the locationManager:didDetermineState:forRegion: callback, which tells you if you are either Inside, Outside or Unknown.
You can force yourself to get a callback by calling
locationManager.requestStateForRegion(region)
when your app starts up.
See more here: https://developer.apple.com/library/ios/documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/#//apple_ref/occ/intfm/CLLocationManagerDelegate/locationManager:didDetermineState:forRegion:
Related
I am working on a project in which i am trying to get location updates in all states, even when app is terminated. I have used all possible solutions but still it's not working in case of termination.For now I want to clear a doubt - I am using startUpdatingLocation() for foreground and background. As we know that startMonitoringSignificantLocationChanges() is the only method that relaunch app in case of any location update. Can we call "startMonitoringSignificantLocationChanges()" in applicationWillTerminate() method? and Will that work and relaunch app when there is any significant location update? Please tell me.
Thank!!
You cannot do that in applicationWillTerminate(),because closure won't return a value right now.If you want to get user location all the time,try Background Mode.
This is the description in Apple Document:
In such a case, the options dictionary passed to the application:willFinishLaunchingWithOptions: and application:didFinishLaunchingWithOptions: methods of your app delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your app was launched because of a location event. Upon relaunch, you must still configure a location manager object and call this method to continue receiving location events. When you restart location services, the current event is delivered to your delegate immediately. In addition, the location property of your location manager object is populated with the most recent location object even before you start location services.
It clearly tells you how to get the location.
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.
I've implemented the use of GeoFences in my app. I've created a new CLLocationManager property and initialised it in my app's viewDidLoad method simply like so:
[[self.locationManager alloc] init];
I set the delegate to self, start monitoring for regions using startMonitoringForRegion:
Then, I emulate my location while running it using Xcode and the methods didEnterRegion and didExitRegion. The app works perfect while running, but I haven't got the chance to test it as I don't know how to emulate my location while the app is terminated, see my other question
Therefore, I was hoping to get some answers on these questions:
Can I manage background work just like normal with the didEnterRegion and didExitRegion methods? Like calculating, etc?
If my app is terminated, I enter a region, open my app - are my variables from didEnterRegion initialised and set up then?
Do I need to do anything else to set it up to work when my app is terminated, except for the normal CLLocationManager setup that I've done so far?
Thanks!
I have an iOS app that uses the CLLocationManager to monitor regions and to get GPS updates. Most of the time, I want my app to continue tracking the cellphone when it goes in background or even when it gets killed, and it works well (I can still see the small arrow in the status bar after my app gets killed). The problem is that I am not able to stop monitoring the regions and GPS updates after my app has been restarted by the Location Services.
When my app gets restarted by the Location Services, I instanciate the CLLocationManager and then call its methods stopRangingBeaconsInRegion and stopUpdatingLocation before setting its delegate to nil and itself to nil.
Thanks to NSLogger, I can see that my callbacks are no longer called, but the small arrow in the status bar stays there (and my app is the only one that I allowed to use the Location Services from the settings menu).
What did I miss? Is there a way to know what still uses the Location Services in my app?
When you call stopRangingBeaconsInRegion, where are you getting the list of regions? The proper way to do this is like below:
for (CLRegion *monitored in [self.locationManager monitoredRegions]) {
NSLog(#"Stopping monitoring on: %#", monitored.identifier);
[self.monitoringLocationManager stopMonitoringForRegion:monitored];
}
for (CLBeaconRegion *region in [self.locationManager rangedRegions]) {
NSLog(#"Stopping ranging on: %# ", region.identifier);
[self.rangingLocationManager stopRangingBeaconsInRegion:region];
}
I finally found that I missed to remove some of my numerous regions. The easy way to avoid this mistake is to retrieve the list of regions monitored with the property monitoredRegions and call stopRangingBeaconsInRegion for each of them. I also forgot to call stopMonitoringSignificantLocationChanges (I didn't know that my app was using it, since I am modifying the app of a former colleague).
How do you know that it is your app that is using the location services?
The small arrow appears if the iOS itself is using the location services in the background.
if you did call stopRangingBeaconsInRegion and stopUpdatingLocation before setting the delegate to nil and you are not getting any callbacks then your app is not using the location services.
GPS signal is lost when App is resumed from long time suspend mode.
And/or after user goes into a building where GPS is weak and then resumes the App.
The blue dot disappears and the map is centered at lat:0 long:0 ( which is somewhere in
the ocean near Nigeria-Africa )
If you launch another GPS app at that point in time, such as Apple Maps,
you DO see the blue dot, even if not so accurate.
The only way a user can fix it - is by killing my app completely and start it again.
It happens on both iOS 5.x and iOS 6.x.
Before going into details, I would really like to ask:
Does anyone encounter this problem ??
Its very annoying but, I couldn't find anyone complaining about this
anywhere on the web - very weird.
I'm using normal CLLocation with showUserLocation=YES,
Nothing magical, no special accuracy tuning or whatever, just simple default
implementation.
I have already tried restarting every possible component when App is resumed;
showUserLocation=NO;
showUserLocation=YES;
or
[locationManager stopUpdatingLocation];
[locationManager startUpdatingLocation];
or
even releasing locationManager and initialize it again doesn't help!
( also tried restarting it with a delay using dispatch_after )
Is there any programmatic way to force RESET the GPS signal or CLLocation in ios ?
Will appreciate any relevant discussion!
I Think you default Location is set "None" so this type of issue created.
Go to
Edite Scheme..
|
|
"Run YourProjectName" / Left Hand Side
|
|
Select "Option" Tab
|
|
Default Location
|
|
Choose any Location such like , "London England"
When you say that you've tried stopping/starting the CLLocationManager object, are you saying that the call-back you get in your delegate gives you a 0,0 coordinate, or are you trying to access the location directly using the location property in CLLocationManager?
I work on a location based app and one thing I can tell you is that you cannot count of directly getting the location of a CLLocationManager object. The only reliable way to get location information is to rely on the callback of the CLLocationManager class by implementing
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
The way I handle CLLocationManager in my app (now I'm not saying this is optimal or ideal for your use case but it does allow us to provide a solid location-based experience to the user on app launch/resume)
Wrap the CLLocationManager into a location management class (usually using a singleton) - I think this can be a subclass of CLLocationManager but in my case it's just a subclass of NSObject with a CLLocationManager object as a property
Store the last known valid location in this singleton, and then write it to disk (NSUserDefaults or another location - need to re-check if you're allowed to store user location in NSUserDefaults but we've done it in our app and doesn't seem to affect the approval process)
Re-implement a way to get the current location in your custom class - basically check if CLLocationManager is returning 0,0 and if it is, return your cached position instead
Not strictly necessary but if you have multiple views/pages that need to use the location, implementing the observer model works well (since your singleton is now CLLocationManager's delegate, you need to have a way to pass this information on to your view controllers).
With the above, on my map page (or wherever I'm displaying user location) - I basically update the map with the cached location once (in viewDidLoad) and then I allow one update to the map through the delegate-callback. Once that call-back is received, I then set showsUserLocation to YES (if the call-back isn't called, then you don't have a valid location yet and so setting showsUserLocation at that point doesn't do anything).
I hope this helps and feel free to let me know if you have any further questions!