I want to get accurate location with google fused location api?

Naimatullah picture Naimatullah · Feb 6, 2015 · Viewed 10k times · Source

I am using Fused location Api, i am getting the location with approximately 10 meters accuracy. Some times it gives 4 to 8 meters accuracy. I want more accuracy using this fused location Api or with any other way. Is there any way to get location with less than 4 meter accuracy.

I am getting location with this way.

    public class GetCurrentLocation implements
            ConnectionCallbacks, OnConnectionFailedListener, LocationListener {

        private static final String TAG = "location-updates-sample";
        public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 0;
        public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
                UPDATE_INTERVAL_IN_MILLISECONDS / 2;
        private final String REQUESTING_LOCATION_UPDATES_KEY = "requesting-location-updates-key";
        private final String LOCATION_KEY = "location-key";
        private final String LAST_UPDATED_TIME_STRING_KEY = "last-updated-time-string-key";
        private GoogleApiClient mGoogleApiClient;
        private LocationRequest mLocationRequest;

        private Context mContext;
        private getLocation mGetCurrentLocation;

        public GetCurrentLocation(Context context) {
            mContext = context;

            buildGoogleApiClient();
        }

        private synchronized void buildGoogleApiClient() {
            Log.i(TAG, "Building GoogleApiClient");
            mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
            createLocationRequest();
        }

        public interface getLocation{
            public void onLocationChanged(Location location);
        }

        public void startGettingLocation(getLocation location) {
            mGetCurrentLocation = location;
            connect();
        }

        public void stopGettingLocation() {
            stopLocationUpdates();
            disconnect();
        }

        private void createLocationRequest() {
            mLocationRequest = new LocationRequest();
            mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
            mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
            mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }

        private void startLocationUpdates() {
            if (mGoogleApiClient.isConnected()) {
                LocationServices.FusedLocationApi.requestLocationUpdates(
                        mGoogleApiClient, mLocationRequest, this);
            }
        }
    private void stopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
    }



    private void connect() {
        mGoogleApiClient.connect();
    }

    private void disconnect() {
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Log.i(TAG, "Connected to GoogleApiClient");
        startLocationUpdates();

    }

    @Override
    public void onLocationChanged(Location location) {
        mGetCurrentLocation.onLocationChanged(location);
    }

    @Override
    public void onConnectionSuspended(int cause) {
        Log.i(TAG, "Connection suspended");
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode());
    }
}

And I am using this class in my activity code.

private GetCurrentLocation mListen;
mListen = new GetCurrentLocation(this);
            mListen.startGettingLocation(new GetCurrentLocation.getLocation() {
                @Override
                public void onLocationChanged(Location location) {
                   // Here is my working with location object
                }

            });

How can i optimize this code to get the accurate location. Thanks.

Answer

Mayank Sharma picture Mayank Sharma · Aug 12, 2019

In 2020 Best Offical Solution

Google API Client/FusedLocationApi are deprecated and Location Manager is not useful at all. So Google prefer Fused Location Provider Using the Google Play services location APIs "FusedLocationProviderClient" is used to get location and its better way for battery saving and accuracy

Here is sample code in kotlin to get the last known location /one-time location( equivalent to the current location)

 // declare a global variable of FusedLocationProviderClient
    private lateinit var fusedLocationClient: FusedLocationProviderClient

// in onCreate() initialize FusedLocationProviderClient
    fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)

 /**
     * call this method for receive location
     * get location and give callback when successfully retrieve
     * function itself check location permission before access related methods
     *
     */
    fun getLastKnownLocation() {
            fusedLocationClient.lastLocation
                .addOnSuccessListener { location->
                    if (location != null) {
                       // use your location object
                        // get latitude , longitude and other info from this
                    }

                }

    }

If your app can continuously track the location then you have to receive Receive location updates

Check the sample for that in kotlin

// declare a global variable FusedLocationProviderClient
        private lateinit var fusedLocationClient: FusedLocationProviderClient
    
    // in onCreate() initialize FusedLocationProviderClient
        fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)
    

      // globally declare LocationRequest
        private lateinit var locationRequest: LocationRequest
    
        // globally declare LocationCallback    
        private lateinit var locationCallback: LocationCallback
    
    
        /**
         * call this method in onCreate
         * onLocationResult call when location is changed 
         */
        private fun getLocationUpdates()
        {
    
                fusedLocationClient = LocationServices.getFusedLocationProviderClient(context!!)
                locationRequest = LocationRequest()
                locationRequest.interval = 50000
                locationRequest.fastestInterval = 50000
                locationRequest.smallestDisplacement = 170f // 170 m = 0.1 mile
                locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY //set according to your app function
                locationCallback = object : LocationCallback() {
                    override fun onLocationResult(locationResult: LocationResult?) {
                        locationResult ?: return
    
                        if (locationResult.locations.isNotEmpty()) {
                            // latest location is on 0th index
                            val location =
                                LatLng(locationResult.locations[0].latitude, locationResult.locations[0].longitude)
                            // use your location object
                            // get latitude , longitude and other info from this
                        }
    
    
                    }
                }
        }
    
        //start location updates
        private fun startLocationUpdates() {
            fusedLocationClient.requestLocationUpdates(
                locationRequest,
                locationCallback,
                null /* Looper */
            )
        }
    
        // stop location updates
        private fun stopLocationUpdates() {
            fusedLocationClient.removeLocationUpdates(locationCallback)
        }
    
        // stop receiving location update when activity not visible/foreground
        override fun onPause() {
            super.onPause()
            stopLocationUpdates()
        }
    
        // start receiving location update when activity  visible/foreground
        override fun onResume() {
            super.onResume()
            startLocationUpdates()
        }

Make sure you take care about Mainfaist permission and runtime permission for location

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

and for Gradle add this

implementation 'com.google.android.gms:play-services-location:17.0.0'

For more details follow these official documents

https://developer.android.com/training/location/retrieve-current

https://developer.android.com/training/location/receive-location-updates

https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderClient