How does LocationManager choose which NETWORK_PROVIDER to use when getting location data? I would like to be able to identify the providers that LocationManager selects the NETWORK_PROVIDER from.
For example, there are two nearby NETWORK_PROVIDER locations, X (close) and Y (not as close). When standing in a single spot, sometimes the NETWORK_PROVIDER will be X, sometimes Y. I assume that the location with the highest accuracy gets returned (which is why usually X is returned), and all other networks are ignored, but I would like to return a list of all the nearby networks (or at least the top 2 or 3) at the same time.
Any of the .getProvider() methods (as far as I know) return the type of the provider (network, gps, passive), but nothing to actually identify the provider. When the location is returned, the location data is unique for the providers, but cannot be used to choose providers. I can get data from X, but I can't tell the program to ignore X (or can I?).
Anyway to make this happen? To return a list or array of NETWORK_PROVIDERS and then step through them getting location data?
And no, using GPS_PROVIDER is not an acceptable answer, because I need NETWORK_PROVIDER data only.
This answer is not based on any evidence, but rather my understanding of how the location provider works. When you request NETWORK_PROVIDER, you're basically asking it to give you the location that they estimate based on all the information that is available. For example, you might have 3 wifi networks and 2 cell towers, and that info is sent up to a server on the internet. Using that info, they calculate where they think you are, and return that to you. So, in other words, the network_provider location is based on the sum of all wifi/cell-tower info available to your phone.
Individually, a wifi hotspot doesn't tell you too much about where you are. A cell tower gives you some location info, but you'll need a few sources to accurately triangulate your location. Also, note that you need a internet/data connection, since the location is determined by some server, and not done on your phone. This is because knowing the nearby wifi hotspots (more specifically the MAC addresses) is useless without a database that maps each hotspot to it's physical location.
Related
Some resources say getLastKnownLocation() merely gives a location of some previous app's Location Change Listener.
But one thing I feel is missing from the conversation -- if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves? So if I call getLastKnownLocation(), isn't it getting the current GPS from the phone's constantly-updated GPS?
If so, then why do people warn against using it / accuse it of potentially getting a "stale" location? If the GPS is being tracked / updated, and getLastKnownLocation() makes a one-time grab of it's current position, what makes getLastKnownLocation() bad?
What am I mistaken about the Locations service or GPS?
The documentation says: Returns a Location indicating the data from the last known location fix obtained from the given provider.
Also, about the "out of date location": This can be done without starting the provider. Note that this location could be out-of-date, for example if the device was turned off and moved to another location. ("This" refers to getting the last known location).
Also, taken from LocationProvider docs:
Each provider has a set of criteria under which it may be used; for example, some providers require GPS hardware and visibility to a number of satellites; others require the use of the cellular radio, or access to a specific carrier's network, or to the internet. They may also have different battery consumption characteristics or monetary costs to the user.
if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves?
Well, it is, but not constantly. This has to do with battery consumption, if the phone was constantly updating the GPS location, the battery life would suffer a lot. The GPS location is usually updated when some app requests it. But even that request is not guaranteed to succeed. For example, suppose your going into a tunnel. Some application requests to update the GPS coordinates right before entering the tunnel and it succeeds. Now, you've entered the tunnel, which is 5km long. Most probably your device won't be able to get a GPS fix from the tunnel, so for the next 5km (at least) getLastKnownLocation() will return an outdated value, since the devices last known location was at the entrance of the tunnel.
What you could do is explicitly request to update the GPS location, that however might take some time and there are no guarantees that it will succeed.
You have the assumption "if the phone has GPS enabled, isn't this GPS tracking/updating as the phone moves". This assumption is incorrect. The GPS functionality takes up a lot of battery life so it should be used sparingly and almost certainly not all the time.
I've developed an app that receives the location from both GPS_PROVIDER and NETWORK_PROVIDER, however the NETWORK_PROVIDER returns the best values retrieved from WIFI and GPRS, without having any control over it. I need to get the value returned by the GPRS location listener even when you have WIFI active, so I can use it to dismiss the fake locations from other apps.
Is it possible to do this?
At the moment I'm testing this solution Disable / Check for Mock Location (prevent gps spoofing) , I'll let you know if it solves my issue
Unfortunately it is not possible, no.
You can do something like this:
final LocationManager locationManager = getLocationManager();
final List<String> providers = locationManager.getProviders(true);
if (providers.size() > 1) {
providers.remove(LocationManager.NETWORK_PROVIDER);
}
But you don't have the option to distinguish between a cell or a wifi network-provider!
This provider determines location based on availability of cell tower
and WiFi access points. Results are retrieved by means of a network
lookup.
Constant Value: "network"
Source: http://developer.android.com/reference/android/location/LocationManager.html#NETWORK_PROVIDER
What you can try is to use this solution. However, since this doesn't seem to be documented I'd be careful relying on it because it might break in future OS versions or might not work on every device.
I'm working on a app which requires that a device with this app installed will automatically find other users within a maximum radius of 200ft (worst case scenario 300ft, but that's pushing it) and/or a minimum radius of 40ft.
Ive tried the obvious solution of using GPS and a MYSQL query that query's our location table for other users within the 200ft radius, but as you probably would guess this is not incredibly accurate and if the device uploads coordinates that are off by over 200ft the server will return a list of users that are not within proximity. While I would prefer to just get the app to work the way it was meant to I'd rather the server return no users than false positives.
I know there's probably no simple way to do it accurately, but what other options do I have? And how did Color manage to do it? With all the tech in the avg smartphone and all the location based apps this has to be possible to do.
200ft (60m) is no Problem for GPS. Usually GPS is below 10m.
You even have a location.getAccuracy() method which you should evaluate
Just use GPS as your only location source. do not use cell tower location provider, when you want accuracy < 60m.
Of course inside a building, when you are sitting at your desktop GPS will not work, or is off by 60m.
GPS needs a view to open sky not obstructed (by dense materials).
Take a look at this question:
how to get the most accurate location using GPS and AGPS with given time in android?
Basically it depends on the phone's GPS and the current environment. Besides that, there's probably nothing you can do to further boost the location accuracy other than using GPS.
I have developed a location based service which identifies the location of the user using GPS. I want to authenticate the data from GPS because an attacker can spoof location information with a simulator.
I've studied an authenticating mechanism from here, but i don't know how to implement the technique they have mentioned.
The idea of the paper is to retrieve geolocation from two different providers. In your case you'd get the device's GPS position for high accuracy and the cell id position to validate this data.
Here's a full example how to get locations by cell id: http://www.devx.com/wireless/Article/40524
You need to define a threshold for the difference of these locations. So we believe the GPS location is faked when the distance between GPS and cellular is greater than our threshold.
Some abstract code example:
static final int THRESHOLD = 2000 // maximum discrepancy in meters
Location getLocationFromGPS();
Location getCellularLocation();
boolean isLocationValid(Location gps) {
Location cell = getCellularLocation();
return gps.distanceTo(cell) <= THRESHOLD;
}
Following this approach there can be two different types of mistakes:
assuming the GPS data is faked but it is not
trust the GPS data while it's faked
Setting small values for THRESHOLD will more and more lead to mistake #1. Most of all users will never fake their GPS data, so claiming they're cheaters won't make your app successful ;-)
The paper states that the Cellular Network Based accuracy is about 100 - 1500 meters. So I highly recommend you to choose values greater than 1500 meters.
Please mind that - as Rune FS mentioned - advanced users may fake both location providers at the same time.
We know there are two positioning mode in Android: GPS and network. If we use network, then Android can use WIFI or 2G/3G cell tower to position. Without GPS, we can simply use LocationManager.NETWORK_PROVIDER to get the location data. But how can we know the mode is WIFI or 2G/3G cell tower exactly? Android doesn't provide separate providers for WIFI and cell tower.
I have thought a method. But I am not sure whether it is correct. Please review and give comments:
Check whether I can get a WIFI hotspot list. If nothing in the list, cell tower must be used.
If there are some WIFI hotspots, and the accuracy is high (<=100m), then WIFI is probably used. If the accuracy is low, is still cell tower used?
In my understanding, the accuracy of WIFI positioning is relatively high. But what's the normal range of the accuracy for it? Another question, does Android use WIFI and cell tower at the same time? If it does, then in my application, I can think it use WIFI, not cell tower.
Thanks!
Actually, there is a way to do this. It is not just documented well and thus might also change without notice.
You can get the used location estimation method via the network location provider location update extra data.
Bundle extras = location.getExtras();
if (extras.containsKey("networkLocationType")) {
String type = extras.getString("networkLocationType");
if (type .equals("cell")) {
// Cell (2G/3G/LTE) is used.
} else if (type .equals("wifi")) {
// Wi-Fi is used.
}
}
This is correct, Android does not explicitely give a way to determine how the network location is computed. The principle of the network provider is to collect all the relevant data on the device, and then send it all to the Google servers, where your location is computed and sent back to you. I am not sure, but the network location might also use the accelerometer/gyro/compass data to improve the accuracy of the location, especially when you compute your location continuously.
So I believe it can use simultaneously cell tower and Wifi info.
Your accuracy method should work in most cases, but is not 100% reliable.
Another possibility is to turn the wifi off, compute a first location fix, then turn it on again and give it another try. by comparing the two locations and their accuracy estimates, you can probably guess the influence of wifi on the location engine at your current location.
Out of curiosity, why do you need this for?