I've been pretty puzzled by this one. It seems as though my implementation of either Google Maps or pulling the users location is wonky. Right now I'm getting extremely scattered results across devices, and I'm not sure why, but the Lat/Long is Zeroing out on occasion.
Does anyone have any ideas?
Here is the method that I'm using to get my current location.
try {
locationListener = new MyLocationListener();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, locationListener);
loc = locationManager.getLastKnownLocation("gps");
if (loc == null) {
loc = locationManager.getLastKnownLocation("network");
}
if (loc != null && loc.getLongitude() != 0.0
&& loc.getLatitude() != 0.0) {
sLng = (loc.getLongitude());
sLat = (loc.getLatitude());
}
} catch (Exception e) {
e.printStackTrace();
}
You're using the last cached location. This is only reliable when GPS has been used recently (after the phone booted)
You have to use location obtained from the onLocationChanged() callback to get more up to date locations.
Related
I have a problem with getting current location because, I have in my MainActivity the listener:
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MINIMUM_TIME_BETWEEN_UPDATE,
MINIMUM_DISTANCECHANGE_FOR_UPDATE,
new MyLocationListener()
);
And I have a second activity where I would, when i click on button, calculate distance from my location and gps coordinate that I will pass with distanceTo and return true if the distance is beetween 0 and 200.
So I have a function in SecondActivity
private boolean checkCoordinate(String gps) {
LocationManager lm = (LocationManager) getSystemService(App.getContext().LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
double currentLongitude = location.getLongitude();
double currentLatitude = location.getLatitude();
Location loc1 = new Location("");
loc1.setLatitude(currentLatitude);
loc1.setLongitude(currentLongitude);
String[] sep = gps.split(",");
double latitude = Double.parseDouble(sep[0]);
double longitude = Double.parseDouble(sep[1]);
Location loc2 = new Location("");
loc2.setLatitude(latitude);
loc2.setLongitude(longitude);
float distanceInMeters = loc1.distanceTo(loc2);
if(distanceInMeters < 200){
return true;
}else{
return false;
}
}
But the problem is that someTimes and maybe when I don't change my location the function:
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
return null, and I don't understand how know my current location because I have already set requestLocationUpdates.
so I how can know my current location?
getLastKnownLocation will return null if GPS based location is disabled in system or there was no GPS fix since system startup. If you want to ensure there is a location you can use the requestSingleUpdate-method, it will not return until there is a location available.
It might also be a good idea to not use the APIs based on specific provider name if it's not important to use a specific provider (usually it is not important how you got the location). The API contains methods that take a Criteria-object instead of a provider name and you can define very precisely what accuracy level etc. you want.
I am trying to retrieve Location as follows:
LocationManager locationManager = (LocationManager)MyApp.getAppContext().getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
// Getting the name of the provider that meets the criteria
String provider = locationManager.getBestProvider(criteria, false);
if(provider!=null && !provider.equals("")){
// NOTE: the location below is null !!
Location location = locationManager.getLastKnownLocation(provider);
String lat = location.getLatitude();
String lng = location.getLongitude();
}
The 'location' above is null. Why?
But when i open the (Google) Maps app - it shows location correctly, and even a notification icon (looks like a exclamation mark) shows up.
And there is a GPS Coordinates app - which also shows up blank.
I have turned on Settings > 'Location' on the phone. If it matters this is Android 4.4.4 Sony Experia phone.
Well, it seems that you're not checking properly if the GPS is working or not. The way you should do it:
final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
if (!manager.isProviderEnabled( LocationManager.GPS_PROVIDER ) ) {
//GPS is not enabled !!
}
You can also create an AlertDialog so the user is aware that the GPS is not enabled and you can send him to the GPS settings by doing this:
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
After this, I'd implement a location listener and get coordinates, here is an example, check it out
How do I get the current GPS location programmatically in Android?
UPDATE: They might be getting coordinates through other provider (usually the one which is working better at that moment). So if the GPS it not working, just try other provider, here is an example:
Location lastKnownLocation = null;
List<String> providers = null;
if(locationManager != null) providers = locationManager.getAllProviders();
if(providers != null)
{
for(int i=0; i<providers.size(); i++)
{
if(locationManager != null) lastKnownLocation = locationManager.getLastKnownLocation(providers.get(i));
if(lastKnownLocation != null)
{
position = new LatLng(lastKnownLocation.getLatitude(), lastKnownLocation.getLongitude());
break;
}
}
}
I have a simple location manager that normally works, however when the Android device has been turned off and then turned back on, the android location manager returns Null even when I have it requesting updates. I am aware that getLastKnownLocation can return null, however I believe I am handling that in my code. All suggestions Appreciated.
Apparently lon = location.getLongitude(); is crashing it.
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null)
{
// request location update!!
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
lon = location.getLongitude();
lat = location.getLatitude();
}
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//Get last known location
location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//Update if not null
if (location != null)
{
lat = location.getLatitude();
lon = location.getLongitude();
}
//Request update as location manager can return null otherwise
else
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
lat = location.getLatitude();
lon = location.getLongitude();
}
}
the android location manager returns Null even when I have it requesting updates
Correct. Requesting updates requests that Android start trying to find out where the device is. That will take a while. In the meantime, getLastKnownLocation() can very well return null.
getLastKnownLocation() is generally only useful if you would like to know the location, but if that data is not ready, you can move on without it. If you need the location, and getLastKnownLocation() returns null, you will to wait to use the Location until onLocationChanged() is called. Note that onLocationChanged() may never be called, as there is no requirement that the user have any location providers enabled, and there is no requirement that the device be in a position to actually get location fixes.
I saw your reply on the airplane mode but you do however have bad practices in your code.
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location == null)
{
// request location update!!
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
lon = location.getLongitude();
lat = location.getLatitude();
}
you already saw here that location in null, that means that you can't access the inner properties such as latitude and longitude. In any case, location requests are asynchronous and it takes a short amount of time for them to start.
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
//Get last known location
location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
//Update if not null
if (location != null)
{
lat = location.getLatitude();
lon = location.getLongitude();
}
//Request update as location manager can return null otherwise
else
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
lat = location.getLatitude();
lon = location.getLongitude();
}
}
Even here, in the "else" clouse, you can't access the location right away. that means that you can't immediately get the location (it will just hold the last value).
What you should do is implement the onLocationChanges method and hadle the location there in asynchronous way. like this:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null)
{
lat = location.getLatitude();
lon = location.getLongitude();
}
else
{
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
}
#Override
public void onLocationChanged(Location location) {
lat = location.getLatitude();
lon = location.getLongitude();
}
The only problem was that I had airplane mode enabled on the Android Phone. I'm a bit embarrassed now!
I am trying to get my current coordinates with network provider and not gps provider.
I was able to figure out the solution for that but I am a bit confused with the concept in this scenario.
Working Code
Here's my code for getting my coordinates:
public void getLocation(){
locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
if(appUtils.isOnline()){
try{
Geocoder geocoder = new Geocoder(
MainActivity.this.getApplicationContext(),
Locale.getDefault());
Location locationNetwork = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
List<Address> list;
if(locationNetwork!=null){
Toast.makeText(context,"Network Available!!",Toast.LENGTH_LONG).show();
list = geocoder.getFromLocation(locationNetwork.getLatitude(),locationNetwork.getLongitude(),3);
if(list!=null&&list.size()>0){
latitude = list.get(0).getLatitude();
longitude = list.get(0).getLongitude();
Toast.makeText(context,String.valueOf(latitude) + " (....) " + String.valueOf(longitude),Toast.LENGTH_LONG).show();
int count = 0;
while (latitude==null||longitude==null){
latitude = list.get(count).getLatitude();
longitude = list.get(count).getLongitude();
count++;
Toast.makeText(context,String.valueOf(latitude) + " --- " + String.valueOf(longitude),Toast.LENGTH_LONG).show();
}
}
}else{
Toast.makeText(context,"No response!!",Toast.LENGTH_LONG).show();
}
}catch (IOException e){
e.printStackTrace();
}
}else{
Toast.makeText(context,"Server not responding",Toast.LENGTH_LONG).show();
}
}
This piece of code is working perfectly fine when the gps is enabled. If gps is disabled, it doesn't work.
Now, if we are setting the location to NETWORK_PROVIDER:
Location locationNetwork = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Why do we still require gps ?
Now if I change it to PASSIVE PROVIDER:
Location locationNetwork = locationManager
.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
It works fine with the passive provider. Why is it that ?
Can someone explain what is the major difference here and what would be the right way to get the coordinates with network provider ?
I know this question is been asked several times and I did went through it. I just want to get cleared with this concept.
Thank's in advance.. :)
It doesn't require GPS to use the network provider, I've done it many times. However, getLastKnowLocation may not return a value if either it has never had an app request updates for that provider, or if the last time that happened was too long ago. You cannot count on that function always returning non-NULL. If you want to ensure that you get a location, use requestSingleUpdate instead. This will always get you a location (assuming the provider you use is enabled), but may take some time- a result may not be immediately available.
(There is one other time that function may never return- if you use the GPS provider and it can't get a lock on enough sattelites to find a location. Such as if you're in an underground parking garage).
This is the bit of code that I use to quickly get the current location, by checking all available network options.
private double[] getGPS(){
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
List<String> providers = lm.getProviders(true);
/* Loop over the array backwards, and if you get an accurate location, then break out the loop*/
Location l = null;
for (int i=providers.size()-1; i>=0; i--) {
l = lm.getLastKnownLocation(providers.get(i));
if (l != null) break;
}
double[] gps = new double[2];
if (l != null) {
gps[0] = l.getLatitude();
gps[1] = l.getLongitude();
}
return gps;
}
I've got Google Maps v2 running on my app, using a service to get the users location. Problem is the location keeps changing. It shows my real location for a bit, then jumps to a random location that I've never been to before.
I'm check GPS/Network lat/lng via the service and calling them in my maps class, where I then animate the camera to move to my location. I don't really know what's wrong, or where to start with this one.
Does anyone know what sort of problem this is? It's baffling to me.
I don't really know what code to post. The accuracy of the location via network is 1121m where as the accuracy of the location via GPS is around 31. I'm using a LocationListener and in the onLocationChanged is says it's using my network location, suddenly the accuracy improves, to 29m, then it suddenly goes back up to 1121m. This happens about every minute or so. Very odd behaviour. With GPS enabled, shouldn't that be the preferred choice anyway? Is there a way to set it to my preferred choice once it gets a fix?
My service gets it's information like this:
public Location getLocation() {
Log.i("getLocation", "Get location called");
try {
locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
//Getting GPS status
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//Getting network status
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (!isGPSEnabled && !isNetworkEnabled) {
// no network provider is enabled and GPS is off.
Log.d("NOT ENABLED", "PASSIVE PROVIDER");
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
loc = locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
if (loc != null) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
Log.i("PASSIVE_LOCATION", "Location: "+loc.toString());
}
}
else {
this.canGetLocation = true;
if (isNetworkEnabled) {
Log.d("Network", "Network");
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
Log.i("NETWORK_LOCATION", "Location: "+loc.toString());
}
}
if (isGPSEnabled) {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
Log.d("GPS Enabled", "GPS Enabled");
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
latitude = loc.getLatitude();
longitude = loc.getLongitude();
Log.i("GPS_LOCATION", "Location: "+loc.toString());
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
//check provider & accuracy
Log.d("PROVIDER", loc.getProvider());
Log.d("ACCURACY", Float.toString(loc.getAccuracy()));
return loc;
If anyone could help I would really appreciate it. Thank you in advance.
I think this solved itself. It was jumping between locations simply because of accuracy. Once GPS accuracy was better than network, it started updating via GPS.
I'm also stopping location updates once the accuracy is less than 30 in onLocationChanged so I have a bit more control and don't waste the users battery.