I am trying to search for best provider with this case below:
// GPS
case R.id.main_menu_gps:
// Set up location services
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
mBestProvider = mLocationManager.getBestProvider(new Criteria(), true);
Log.d(DEB_TAG, "####Value of mBestProvider is " + mBestProvider);
if(mBestProvider != null){
showGpsSearchingDialog();
mLocationManager.requestLocationUpdates(mBestProvider, 150000, 1, this);
} else {
Log.d(DEB_TAG, "Provider is null");
showGpsAlertDialog();
}
break;
My device is returning "GPS" as the best provider but is not able to find a location and my progress dialogue is displayed forever searching. If I go into the phone settings of "Location/Security" and check the "Use wireless networks" the best provider is Network and it works to return a location.
Am I doing something wrong when the best provider is GPS and no data is returned?
You may take a look at my strategy to choose best provider What is the simplest and most robust way to get the user's current location on Android?
If GPS is enabled it will always return GPS as the best provider since you specified an empty criteria. It can take a decently delay for a GPS fix and if you are in a building you may never get a fix at all. So if the network location will be acceptable then you should just do network. Or have a timeout so that at some point you stop waiting on gps and then switch to network instead. If you are using a MapView, you may want to use the MyLocationOverlay because it's internal logic will handle that for you.
Your code looks fine btw.
You aren't really doing anything wrong, there are just certain techniques for gaining the location via GPS. The main issue is that the GPS location may be the best available provider (in terms of accuracy) however it may not be able to obtain the current location do to network/structural obstruction. Without logic in place to determine the amount of time that has gone by while the provider has attempted to attain the location unsuccessfully or without the accuracy required; you may never get the location via GPS and will have to use a different provider or the last known location as a fall-back.
Related
I am developing an Android application in which I am using current location of my device. I am using requestLocationUpdates("gps", 5000, 0, new LocationDetector()); method of LocationManager for getting updates. And inside onLocationChanged() method of LocationListener I am making use of my device's current location. Now:
Question#1: I have recorded that the current location detected by "gps" as well as by NETWORK_PROVIDER has some error (error means my device's location is not exactly that which is returned by "gps" or "network_provider"). So I want to know that what is the maximum error that can be there in the result of "gps" and NETWORK_PROVIDER? And is there any way to get accurate results from "gps" and NETWORK_PROVIDER?
Question#2: In my device, "gps" does not works within closed areas (like room), so I want to make use of "gps" as well as NETWORK_PROVIDER for getting location's updates. So that when my device's "gps" is not working, I should automatically get updates through NETWORK_PROVIDER. So please tell how can I do that?
Question 1
Each provider has pros and cons, gps gives more accurate results with more power usage. Network provider gives less accurate results with less power usage. You can combine gps and network providers but there is already a provider which wraps all things under the hood for you : fused location provider
Question 2
Yes, you can implement a simple timeout mechanism on gps provider. So when timed out, start location requests for network provider.
But i suggest watching this video. So it's good explanation for
your second question.
There are a number of workarounds for detecting the possibility of a fake location being returned by the LocationManager API. those include checking if the mock location setting is enabled and checking the list of installed apps for the ones using the mock location permission. if any of the above happens we could go with removing the TestProvider from the current LocationManager instance and getting a location again, just in case the api returns bogus results. however the above approach wont work with the FusedLocationAPI. is it always granted to return the real location ? or should i consider changing my code to use the LocationManager ?
because of the nature of product i'm working on, it is necessary to be sure of the location.
thanks in advance
From android documentation LocationManager.getLastKnownLocation():
Returns a Location indicating the data from the last known location
fix obtained from the given provider.
Note that this location could be out-of-date, for example if the device was turned off and moved to another location.
How often provider updates device location ? How its works ?
The reason why I asking is that I dont want to use locationListener,
I just need to get current geo location on button click, and thats it.
Can I just do like this ?
final LocationManager mlocManager = (LocationManager) getActivity()
.getSystemService(Context.LOCATION_SERVICE);
final Location currentGeoLocation = mlocManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
How often provider updates device location ? How its works ?
It depends, and you may never know. If a device has good reception then updates about the user's location will fire rapidly.
Can I just do like this ?
Not really. If that is firing too soon then you will not get any location back. If the user doesn't have great reception then it could take 10 seconds before you have a reasonable idea of the user's location. I think you'll have to approach this slightly differently. I'm afraid I must recommend locationListeners :P
if you absolutely can't wait for a location you can try getLastKnownLocation(), but you need to be prepared to have a NULL result.
getLastKnownLocation() is just a cache of the last location from the provider you specified. In some cases there won't be one at all, like when the phone just rebooted. Even when there is a cached location it may not be accurate.
I want to make sure the location received by the LocationListener is a "real" one and doesn't come from a spoofed source (I.e the Application Location Spoofer). I don't care about "but the user sometimes want to spoof the location" - it's about an app which doesnt get distributed over the android market. The application does not need the location to be that accurate - it just has to be "real".
Do you think there is a way to check if the location has been spoofed?What do you think is a good way to prevent location spoofing?Is there maybe a android-method which gives me the real location nevertheless?Is there maybe a android-method to determine if the location has been spoofed?
Thoughts I had:
Check on a blacklist if a location-spoofing app is installed
Enable/disable different location providers and check against their returned locations
Run a background service watching the location (in a passive way) and check for sudden location changes
Please give me your thoughts and input to this issue.
From the Provider name: 'gps' or 'network' are proper
Most spoofers forget to send GPS status updates. That is something that you can use to your advantage
// returns true if mock location enabled, false if not enabled.
if (Settings.Secure.getString(getContentResolver(),
Settings.Secure.ALLOW_MOCK_LOCATION).equals("0"))
return false;
else return true;
The best method is this :
Mock location providers do not send NMEA data. So create a NMEA listener. If you don't get NMEA update but you get valid GPS updates in onLocationChanged() a spoof is being used.
Have a look on "Maintaining a current best estimate" topic on the following page:
Maintaining a current best estimate
I have implemented a locationlistener in my app which uses the Network Provider.
This all works fine because i want a location quickly and with GPS Provider it takes ages.
But I've come to a point in my app where location has to be accurate (max 5-10meters).
I was wondering if it's possible to use the GPS provider with the Network Provider at the same time and then get the best result of both?
And is it also possible to let me know when the GPS provider provided me with an GPS Location?
So basically:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
Will this work with the same overridden onLocationChanged() ?
And how can I see if the GPS has gotten a Location?
Thanks,
You can certainly use the same listener for multiple providers. It may be better to use locationmanager.getProviders with a Criteria object then sort by accuracy or just listen to all of them. Not much practical difference though.
The onLocationChanged callback gives you a Location object, which has a getProvider() method you can use to determine where it came from. It also has a getAccuracy() method, so you could also sort your recent fixes by accuracy.
Ideally, if you are not concerned on the battery usage, then it perfectly fine to use both providers. As Daren explained, you can filters the coordinates by using getProvider() and getAccuracy().
http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/
Ideally, if u are using the same listener for multiple providers there are 2 issues to it.
1.) You are requesting location from multiple providers thus more continuous use Battery. - This can be mitigate depending on your use case. You can unregister the listener once u have received a good location (i.e. - not require a continuous location updates for long).
2.) Making your listener synchronized - And this is important, for code to be more stable - You do not know how these listeners would be called. If internally Android calculate the location from different provider on a different thread than ur listener maybe called on the same main thread from 2 different call points. Same listener object is called.