Determining iOS Location Services' mode of update - ios

I'm building a little prototype app to test Location Services. My app uses both -startUpdatingLocation and -startMonitoringSignificantLocationChanges (for background processing).
In both cases, I'm trying to send a json object to a server with the location data I get, but I'd like to be able to also send some sort of identifier so I can determine which mode of location service was used to acquire the data (GPS, wifi, tower or at least if it was through one of the two services above.
I'm setting up my CLLocationManager in the AppDelegate if that makes any difference.
Thanks

The sources that CLLocationManager uses are not provided. However, you can determine whether GPS is allowed to turn off by setting the desiredAccuracy property. As the documentation notes, an accuracy of 1 kilometer may have the GPS turn off.
For example, setting the desired accuracy for location events to one kilometer gives the location manager the flexibility to turn off GPS hardware and rely solely on the WiFi or cell radios. Turning off GPS hardware can lead to significant power savings.
You don't exactly control the GPS because other apps may be requesting a greater accuracy in the background.
You can roughly guess what was used for determining your location by examining your CLLocation object. Each CLLocation object has a property called horizontalAccuracy. This value is measured in meters. If it is less than 1 kilometer then GPS was probably used.

Related

how to get the location with the CLLocationManager every 10 secondes?

I want to get the different locations of the users in order to display him the trips he did. But in order to save my user's battery, I want to get his location just every 10 seconds with my CLLocation manager.
I first thought about not implementing the 10 seconds interval and get the user's location every time he move with the didUpdateLocations of the CLLocationManager, but when I simulate a drive I get new location every second and I think this is really bad for the battery, am I right ?
Do not try to second guess the location manager. Your job is to set its properties appropriately, such as distanceFilter, desiredAccuracy and activityType. Apple will use every trick in the book to keep battery usage reasonable given your settings. As the docs tell you:
Core Location manages power aggressively by turning off hardware when it is not needed. For example, setting the desired accuracy for location events to one kilometer gives the location manager the flexibility to turn off GPS hardware and rely solely on the WiFi or cell radios, which can lead to significant power savings.
If the goal is track location in the background, there are special modes for that, which save even more.
Check location every 10 second a lot frequent, it will be drain user's battery too fast.
If you would save battery, you should learn apple guide about location manager.
You need use distanceFilter and desiredAccuracy
Base guide CLLocationManager
Energy Efficiency Guide for iOS Apps
Location Awareness Programming Guide - Tips for Conserving Battery Power
Update
Also you can check how fast user moving CLLocation have speed and adjust activityType

Detecting tunnels with Core Location

I am using Core Location for turn by turn based navigation and would like to show a "GPS lost" alert in tunnels.
The problem is that the following two scenarios look the same to the app:
The user drives into a tunnel. GPS updates cease because there is no way to know where the user is.
The user stops at an intersection. GPS updates cease because the user is no longer moving.
I need to set these two situations apart. Ideas?
I have tried looking at the horizontalAccuracy property, but sometimes the updates cease completely, so there is no new horizontalAccuracy information.
Normally with CLLocationManager set for best accuracy for navigation and no distance filter, you should get a location update once a second even if you are stopped at an intersection.
If you stop getting those updates while the motion coprocessor (using CMMotionActivityManager) says you are still driving then you can infer that you are in a tunnel (or underground car park or someplace with a bad GPS signal).
BTW, GPS updates should not stop when you are stopped at an intersection if you have set distanceFilter = 0 and desiredAccuracy = kCLLocationAccuracyBestForNavigation and activityType = CLActivityTypeAutomotiveNavigation, etc.
Another thing to watch out for, if the tunnel has cellular coverage, you may still get location update from cellular triangulation but with worse accuracy. If the CLLocation.horizontalAccuracy goes from less than 50m to over 300m then you have lost GPS/GLONASS coverage even though you are still getting location updates.
Look at locationManager:didFailWithError: method:
If the location service is unable to retrieve a location right away,
it reports a kCLErrorLocationUnknown error and keeps trying.
To determine a second situation (user stops) use locationManagerDidPauseLocationUpdates: method:
When the location manager detects that the device’s location is not
changing, it can pause the delivery of updates in order to shut down
the appropriate hardware and save power. When it does this, it calls
this method to let your app know that this has happened.

In ios, is it possible to know if the GPS location is not being updated?

I'm creating an app that allows the user to navigate with a map when offline (no internet connection or wifi available), and I want to let the user know if the gps location not being updated. I know I can get the last updated location timestamp and the accuracy, but is it possible to know if the gps has no reception?
No, there's no public interface for finding out about the state of specific location hardware such as the GPS receiver.
The Location Manager abstracts all that away, so that developers can get location and accuracy information without worrying about whether the device used GPS, Wifi, iBeacons, cell tower locations, Loran-C, celestial navigation, etc. to determine the location. This is generally a very good thing because it means that your apps work on all devices regardless of whether they have GPS, and will continue to work (and maybe even work better) on new devices that might use other technology. But it also means that you don't get to ask the question "is the device receiving a GPS signal right now?"
Is it possible to know if the GPS location is not being updated?
No. It doesn't seem possible given the available API.
There are a few things about GPS to consider, if you haven't already. It is technically possible to receive a location update from CLLocationManager when you're "offline" but it will depend on several things:
If your device actually has GPS hardware. Some don't.
If you have line of sight to GPS satellites. There's a difference between GPS and A-GPS
Those true GPS updates will come much less frequently because of the way GPS works, but it should work.
... but is it possible to know if the gps has no reception
Based on the way GPS works (as best I understand it) you either turn the radio on/off (-startUpdatingLocation/-stopUpdatingLocation) with the Location Services API and you either get locations more frequently with A-GPS or infrequently with pure GPS when you don't have a network signal. I don't think the Location Services API has a way of telling you "I don't have a GPS signal at all."

How to get the location provider name in iOS?

In Android whenever you get location object you could call "location.getProvider" on the instance to get value like "wifi". Is there something similar in iOS (CLLocation)?
The Location Awareness Programming Guide says:
The [CoreLocation] framework uses information obtained from the built-in cellular, Wi-Fi, or GPS hardware to triangulate a location fix for the device. It reports that location to your code and, depending on how you configure the service, also provides periodic updates as it receives new or improved data
Having said that, you do not have access to how precisely the CLLocationManager determined your location (other than, if you used significant change, that it probably used cell towers). You theoretically could use Reachability to see if you have Wi-Fi availability, but you have no assurances as to what mix of GPS, cellular, and Wi-Fi it used to get your location (even if you happen to have WiFi connection).
What you do have is horizontalAccuracy, which tells you approximately how accurate the location you received is. From a user's perspective, that's probably a more important piece of information.
There isn't a concept of what system provided you with the location on iOS. What you can do is check what the accuracy of the location is. Based on how precise the location is, you can probably surmise if the location was provided by a GPS signal.
The reason this isn't given is that iOS will provide you with an initial location which won't be very accurate (likely based on geo-ip or cell triangulation) and then update the location with more and more precise coordinates if GPS is available.
If your application requires the accuracy provided by a GPS chip, you can add UIRequiredDeviceCapabilities = gps to your Info.plist.

About updating the GPS at the background

I am testing some GPS algorithms with the battery life. I just wrote a very simple app using core-location framework and the app update the gps location every second.
I am wondering how can I change the time interval to update my location, like 10s, 1min, etc?
And when my app is at the background it's stop updating the GPS, do you know how to keep it updating at the background?
be aware that iOS usually does not allow background operations in most cases.
But at least there are three options to "permanently" determine the location:
As you wrote: determine location all the time when your app is not in background. (1)
determine location all the time - also in background. You need to update your Info.plist and add location as a required background service (required for location tracking, Google Latitiude for instance) (take a look at api)
get location updates only when the location changes significantly.
You are not able to change time intervals or something like that. You only have theses three options - and you can get location information only once when you need them, but that was not the intent of your question.
I am wondering how can I change the time interval to update my
location, like 10s, 1min, etc?
This is not possible and it would not make sense, because the GPS chip needs the same power if it a position is needed once a second or evry 10 seconds. Of course you can ignore positions if you dont like them (if they come to often).
The settings of desiredAccuracy influences the power:
kCLLocationAccuracyBestForNavigation: enabled GPS and Acceleration sensors
kCLLocationAccuracyBest: enables GPS but no Acceleration sensors (Cell Tower locating if needed)
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer, kCLLocationAccuracyKilometer: more likely to use Cell Tower or Wifi locating if available.
That uses less power (more likely) but accuracy is lower.
And when my app is at the background it's stop updating the GPS, do
you know how to keep it updating at the background?
If your read Apple's LocationAwarnessGuide ypou find the info, how to set the correct key in Info.plist file.
Since ios 6 there is an additional variant, which should save more power:
There is the method: didUpdateLocations (note: plural!):
This will deliver all locations at once such that it ios does not need to keep your application living in background. Once the app enters foreground you will receive all positions at once.

Resources