I am using the Criteria object to get the best provider like so
final boolean isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if(isGpsEnabled) {
Criteria crit = new Criteria();
crit.setAccuracy(Criteria.ACCURACY_FINE);
crit.setCostAllowed(true);
crit.setPowerRequirement(Criteria.NO_REQUIREMENT);
crit.setSpeedRequirement(false);
String provider = locationManager.getBestProvider(criteria, true);
locationManager.requestLocationUpdates(provider, 600000, 0, new myLocationListener());
}
On my phone (Android 4.1) I have both "Use GPS Satellites" and "Use Wireless Networks" options enabled. Now, the above code works great when I am outdoors and it gives me the GPS location.
But, when I am indoors it does not revert to the "network" provider. It just keeps trying to get the location via GPS and never get its (I wait 1 minute or so)
When I change the code of Criteria to use Criteria.ACCURACY_COARSE then it uses "network" provider.
How do I get it to first try the GPS (because it is enabled) and because we are indoor it will not be able to connect to a satellite to then fall back to using the "network". I can't get that working easily. I state again, GPS is enabled but no access to satellites so want it to get network location instead.
Thanks.
The solution was create the location manager and attach 2 listeners to receive updates. One for GPS and another for NETWORK. You set it to receive updates fairly quickly (or depending on your own case, I just needed to get the location) You then create a method that compares the location of the GPS and Network and find which one is more accurate. You do this at most 3 times to get on average which one is returning the most accurate position and then you stop the location updates.
Related
I am trying to log information about how the app is fetching the coordinates. This is the code I used to grab the coordinates.
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
My question is, how do I find out the source of the coordinates? (GPS, Network Triangulation, Wifi, etc. )
In other words, getLastKnownLocation returns coordinates from multiple sources, how do I get a string name of the source?
You use 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.
GPS_PROVIDER determines location using satellites.
I've written an android application that needs the user location, it was working fine when I used gps provider, but I don't want to use GPS because it uses a lot of battery, here is my code
LocationManager locaionManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,5*1000,0, new MyLocaionListener());
Location loco = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Log.d("enabled=" ,"" + locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
This code returns a null Location Object, and the logCat shows enabled=false when the location service is disabled although I'm using NETWORK_PROVIDER But when I enable the location service from the phone settings I get enabled=true and I get my current location.
So my question is:
does network provider also uses the phone GPS? and how do GPS and NETWORK providers internally works.
I've taken a look at this page: http://developer.android.com/reference/android/provider/Settings.Secure.html#LOCATION_MODE , but I'm still lost.
I know that the Location mode should return an integer. Battery Saving would be 2, High Accuracy would be 3 and if GPS is off then it should return 0.
I have no problem grabbing the current location...
LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location location = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
double longitude = location.getLongitude();
double latitude = location.getLatitude();
String stlongitude = Double.toString(longitude);
String stlatitude = Double.toString(latitude);
But when the phone's location mode is set to Device Only then I have to use LocationManager's GPS_PROVIDER. Which is not as accurate as the NETWORK_PROVIDER. I would like to do an if, else or a case statement that allows me to get the current location mode and if it's set to High Accuracy or Battery saving, use the NETWORK_PROVIDER but if it's set to Device Only use GPS_PROVIDER.
What you are trying to do with Settings.Secure and LOCATION_MODE is the right way to get the enabled providers if you are only interested in targeting devices that are KitKat or above (API 19). But, more than likely, you actually want your app to work with devices that have earlier versions of Android.
Here's code that gets the last location using the least power-hungry provider that the user has enabled:
LocationManager manager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
boolean isGpsEnabled = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkEnabled = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isGpsEnabled && !isNetworkEnabled) {
Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else {
Location location = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
NETWORK_PROVIDER is not as accurate as GPS,
The first thing to note is that NETWORK_PROVIDER is not as accurate as GPS, according to the developer docs, network prodiver uses
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.
The most accurate provider you can use when retrieving the users, location is the GPS, which is defined by the Andorid Developer docs as:
GPS_PROVIDER
This provider determines location using satellites. Depending on conditions, this provider may take a while to return a location fix. Requires the permission ACCESS_FINE_LOCATION.
Manipulating the provider
With that in mind, the following hints will enable you to manoeuvre the logic any way you wish:
1) To set the location manager to recieve updates using best provider the device is capable of using, you can call
/* Getting the name of the BEST provider available */
provider = locationManager.getBestProvider(criteria, true);
/* Getting Current Location using the best provider available */
location = locationManager.getLastKnownLocation(provider);
locationManager.requestLocationUpdates(provider, 300000, 0, this);
2) If you which to force network provider, set your location manager to ask for network provider update like this:
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 60000, 0, this);
3) Similarly, if you which to force GPS use:
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000, 0, this);
I think if you are looking for LOCATION_MODE, not a provider, you should check out this question and response: Change Location Mode to High Accuracy Programmatically Android
Because even if all your providers are enabled, the location mode could mean that it would fail to get a good location if you are in a building and the mode is LOCATION_MODE_SENSORS_ONLY.
I'm working on an application which uses location.
My problem:
When I'm looking for the best provider, I only get the "network".
I know why but I don't know how to improve this.
In the locations settings, when I check "parameter -> location" and "security settings -> Use wireless network", the LocationManager.getBestProvider() returns only network. When it is not checked, and the GPS is active, getBestProvider returns the GPS.
What I want to do is:
When both options are checked, how to use / detect the GPS, instead of the network, as the location provider.
You have to first check whether GPS is on or not. If it is on then get the location from GPS, if not get the location from network.
To check the gps status use :
manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE );
boolean statusOfGPS = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
Given this code
if (!locator.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
//consider forcing user to turn on gps here
} else {
provider = LocationManager.GPS_PROVIDER;
}
What happens if the device does not have GPS. Right now if that provider isn't enabled then it I will jump the user to their system settings to turn it on. But what if it isn't there? How would this be handled. I dont want to necessarily lock those kind of users out of the app.
If the GPS provider is not available (or enabled), then try for whatever you can get:
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_HIGH);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
String provider = lm.getBestProvider(criteria, true);
This assumes that you prefer a rough position over no position at all.
You only need the GPS if you want precise locations. If the device simply does not have a GPS, then you can estimate with less accuracy through the NETWORK_PROVIDER. That's usually suitable if you just need the general location of a user (west side of a city, near a memorial, etc.). If you absolutely need a specific location that's within a specific accuracy for your app to work, then you're user without GPS is just out of luck.
Alternatively, if you enable GPS and the user doesn't have GPS, it simply won't get updates. In that case, you'll have to mention that the updates aren't precise because of lack of GPS, and the user will have to use a weaker version of your app.