Getting current Location in Android using FusedLocationApi

Recently we’ve been working on a project based on user’s current location. Location was very important factor because we were showing it on the map while app was working in the foreground, so there was no need to retrieve location while app is in the background. Since in the past we were not satisfied enough using Location Manager, we decided to give the opportunity to new FusedLocationAPI from the newest Google Play services. I will write here a simple tutorial of how to use it.

FusedLocationAPI

Using the Google Play services location APIs, your app can request the last known location of the user's device. In most cases, you are interested in the user's current location, which is usually equivalent to the last known location of the device. Specifically, use the fused location provider to retrieve the device's last known location. The fused location provider is one of the location APIs in Google Play services. It manages the underlying location technology and provides a simple API so that you can specify requirements at a high level, like high accuracy or low power. It also optimizes the device's use of battery power.

Dependency

Fused location requires the latest version of Google Play Services Location which you have to include in your app/build.gradle file:

dependencies {
    compile ‘com.google.android.gms:play-services-location:10.2.1'
}

You can check the official site to get the latest version.

Permissions

You have to add the following permissions to AndroidManifest.xml:

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

Since there is a new permission model from Android Marshmallow, you will have to check location permissions at runtime.

if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
    ...
}

Before going further it is also useful to check in code if play services are available.

private boolean isPlayServicesAvailable(Context context) {
        int resultCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context);
        if (resultCode != ConnectionResult.SUCCESS) {
            GoogleApiAvailability.getInstance().getErrorDialog((Activity) context, resultCode, 2).show();
            return false;
        }
        return true;
    }

LocationServices API

Finally we are getting to the point where you can create your GoogleApiClient and LocationRequest.

protected void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        createLocationRequest();
    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setSmallestDisplacement(5f);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

Location request is important for collecting constant location updates in LocationListener. In this example you will receive new location update if displacement is bigger than 5 meters and if time interval is bigger than 1 second. You can check here all the possibilities.

After you created GoogleApiClient and LocationRequest you can connect the client and in ConnectionCallback retrieve the last known location as also start with location polling.

@Override
    public void onConnected(@Nullable Bundle bundle) {

        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            PermissionsManager.get().requestLocationPermission(this);
            return;
        }

        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (location != null){
            onLocationChanged(location);
        }

        startLocationUpdates();
    }

protected void startLocationUpdates() {
    // Create the location request
    mLocationRequest = LocationRequest.create()
        .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
        .setInterval(UPDATE_INTERVAL)
        .setFastestInterval(FASTEST_INTERVAL);
    // Request location updates
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
        mLocationRequest, this);
}

If you don’t want to receive location updates anymore, you have to remove LocationRequest from GoogleApiClient and disconnect it.

if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }

Summary

This example is showing just the basic flow of how it should be implemented, the rest depends on your requirements of the project. This is working excellent until now for us and it should be helpful for everybody working on location based apps.