I have developed one application which is used to find current location of device. I have used Fused Location API to get current location.
I am facing very strange issue, in some of devices i am not getting accurate current location until i open inbuilt Google Map, once i open Google Map and back to my application at that time application return exact location.
Here is my Location Request.
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setSmallestDisplacement(DISPLACEMENT); // 10 meters
Can anyone tell me what is the wrong? Your help is really appreciated.
So Waze and we used FusedLocation in past and faced a lot of problems.
The API is broken. There are some devices that not perf it properly. Activity recognition that fused a lot relay not working and recognize staff properly.
We end, to switching back to location manager API.
Here the snippet:
Init location manager and start to request the updates on different thread.
I personally register separate listeners for each provider
if (mLocationManager == null) {
LOGGER.info("Location track,start called first time. Creating Location Manager");
mLocationManager = (LocationManager) mContextWeakReference.get()
.getSystemService(Context.LOCATION_SERVICE);
mLocationHandlerThread
= new HandlerThread("LocationThread", Thread.NORM_PRIORITY);
mLocationHandlerThread.start();
// Now get the Looper from the HandlerThread
// NOTE: This call will block until the HandlerThread gets control and initializes its Looper
Looper looper = mLocationHandlerThread.getLooper();
Location networkLastKnownLocation = null;
Location gpsLastKnownLocation = null;
mGpsLocationListener = new GpsLocationListener();
mNetworkLocationListener = new NetworkLocationListener();
// Register the listener with the Location Manager to receive location updates
if (mLocationManager.getAllProviders().contains(LocationManager.GPS_PROVIDER)) {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
mGpsLocationListener,
looper);
gpsLastKnownLocation = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else {
setGpsProviderAvailable(false);
}
if (mLocationManager.getAllProviders().contains(LocationManager.NETWORK_PROVIDER)) {
networkLastKnownLocation = mLocationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
LOCATION_REQUEST_INTERVAL_MILLIS, SMALLEST_DISPLACEMENT_METERS,
mNetworkLocationListener,
looper);
}
setLastKnownLocationDifferentProviders(gpsLastKnownLocation,
networkLastKnownLocation);
}
And the listeners are:
public class GpsLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
LOGGER.info("Location track ,onLocationChanged location={}", location);
switch (location.getProvider()) {
case LocationManager.GPS_PROVIDER:
if (mLocationManager != null) {
mLocationManager.removeUpdates(mNetworkLocationListener);
}
break;
}
setLastKnownLocation(location);
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
}
@Override
public void onProviderEnabled(String provider) {
LOGGER.info("onProviderEnabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(true);
}
}
@Override
public void onProviderDisabled(String provider) {
LOGGER.info("onProviderDisabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(false);
}
}
}
public class NetworkLocationListener implements LocationListener {
@Override
public void onLocationChanged(Location location) {
LOGGER.info("Location track ,onLocationChanged location={}", location);
switch (location.getProvider()) {
case LocationManager.NETWORK_PROVIDER:
setLastKnownLocation(location);
break;
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
LOGGER.info("onStatusChanged: {}, status: {}", provider, status);
}
@Override
public void onProviderEnabled(String provider) {
LOGGER.info("onProviderEnabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(true);
}
}
@Override
public void onProviderDisabled(String provider) {
LOGGER.info("onProviderDisabled: " + provider);
if (provider.equals(LocationManager.GPS_PROVIDER)) {
setGpsProviderAvailable(false);
}
}
}
Don’t forgot to unregister and stop all threads 🙂
Answer:
While creating LocationRequest, You must have setPriority() to PRIORITY_NO_POWER.
PRIORITY_NO_POWER means your app will never get any location unless other app in phone had requested for locations and it received. Read more at LocationRequest.
Answer:
I am not sure about this, but last I had seen anything like this, that phone didn’t not have dedicated GPS. It only had a-GPS.
After toying around for lot of time I realised that this was the reason why I wasn’t getting accurate location. But after opening maps, for some reason location was accurate. Google definitely does lot of other things in maps to fetch accurate location on maps even if the phone doesn’t have dedicated GPS. Just check the devices and their hardware specs.
Answer:
Are you guys testing on Marshmallow or above version device ?
In devices above than Lollipop, You have to request for Location permission at run time. Refer this link http://developer.android.com/training/permissions/requesting.html
So your wouldn’t have location permission,hence it would not return accurate location but when you start your Map app that has already have Gps permission, will update your location in Google play service. So your also start showing correct location because location is ultimately fetched from Google play service.
Tags: androidandroid