FusedLocationProviderClient | Get Current Location Android Example

fusedlocationproviderclient
Spread knowledge

So far we had used FusedLocationProviderApi to fetch user’s location. But as of Google Play Services version 11.6.0, it has been depreciated and now Google recommends us to use FusedLocationProviderClient. In this tutorial we will be explaining why FusedLocationProviderClient is better and how should we implement it.

FusedLocationProviderClient is the main entry point to Google’s LocationServices. With this your app no longer needs to manually manage connections to Google Play Services through GoogleApiClient.

 

If you want to check how current location was fetched with now depreciated FusedLocationProviderAPI read this

Why FusedLocationProviderClient ?

Google’s LocationServices API is the one which is actually used to access device location. To access these services your app needs to connect to Google Play Services. With FusedLocationProviderApi it was our responsibility to initiate and manage the connection. Below code snippet might remind you of how complicated it was to connect to Google Play Services

public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

        private GoogleApiClient googleApiClient;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_maps);

            //Instantiating the GoogleApiClient
            googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        }

        public void onStart() {
            super.onStart();
            // Initiating the connection
            googleApiClient.connect();
        }

        public void onStop() {
            super.onStop();
            // Disconnecting the connection
            googleApiClient.disconnect();

        }

        //Callback invoked once the GoogleApiClient is connected successfully
        @Override
        public void onConnected(Bundle bundle) {
            //Fetching the last known location using the FusedLocationProviderApi
        }

        @Override
        public void onConnectionSuspended(int i) {

        }

        //Callback invoked if the GoogleApiClient connection fails
        @Override
        public void onConnectionFailed(ConnectionResult connectionResult) {

        }
}

 

As you can see, before we could fetch location we first had to initiate the connection to GooglePlayServices and only after the connection was successful we could fetch location. And if we tried to fetch the location before the connection is complete it would lead to a FATAL IllegalStateException. This approach has a lot of issues like

  • The scenario in which connection to GooglePlayServices fails or is cancelled is not handled.
  •  It would be difficult to share the location between multiple activities without repeating the connection logic again
  • For a app which just wants to fetch location understanding and managing this connection logic every time would be an unnecessary and extra effort

Advantages with FusedLocationProviderClient

  • It takes the complete connection logic under the hood. User no longer needs to initialize GoogleApiClient nor does he need to manage the connection logic.
  • It returns the result as a Task object which is easy to a manage and share.
  • User need not wait until the connection is established to request for a Location. When requesting for the current location the API call automatically waits until the connection is estabilished thereby minimising the chances of an IllegalStateException

It’s recommended to use Google Play services version 11.6.0 or higher, which includes bug fixes for this class.

Example: Fetching Current Location

In this example we have a button in an Activity which when clicked would fetch the current location of the user using FusedLocationProviderClient.

  • App permissions need to be defined in the Manifest file. Thereby the first step would be to add the Location permissions in the AndroidManifest.xml
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  • Fused Location provider is a part of Google Play Services therefore we need to include the google play services as dependency in build.gradle.
    implementation 'com.google.android.gms:play-services:11.6.0'
  • Add a button to the layout file of the Launcher Activity
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <Button
            android:layout_width="wrap_content"
            android:id="@+id/button"
            android:text="FETCH Location"
            android:layout_centerInParent="true"
            android:layout_height="wrap_content" />
    
    </RelativeLayout>
    
  • Now initialize that button and implement the OnClickListener in your MainActivity.java file.
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        Button button;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            button = findViewById(R.id.button);
            button.setOnClickListener(this);
    
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.button:
                    break;
            }
        }
    }

     

  • As of Android Marshmallow Location permissions need to be explicitly approved by the user before the app begins to collect device location. To learn more about this read this.
  • We had already mentioned that FusedLocationProviderClient takes care of all the connection logic on its own. Therefore we don’t need to initialize GoogleApiClient nor do we need to implement connection callbacks. We only need to initialize the FusedLocationProviderClient as shown below
    FusedLocationProviderClient fusedLocationProviderClient=LocationServices.getFusedLocationProviderClient(this);
  • Once we have FusedLocationProviderClient we can fetch the current location using the getLastLocation() API. It returns Task object which represents a asynchronous operation. Read more about Task API here.
    Task<Location> task = fusedLocationProviderClient.getLastLocation();
  • We will add the success callback listener to the Task object which will be invoked once the connection is established and the location is fetched.
    task.addOnSuccessListener(new OnSuccessListener<Location>() {
        @Override
        public void onSuccess(Location location) {
           if(location!=null) {
                //Write your implemenation here
                Log.d("AndroidClarified",location.getLatitude()+" "+location.getLongitude());      }
           }
    });

    You must have noticed we add a null check for location in OnSuccessListener. This is to avoid crashes in some scenarios in which the location can be null. Below are some of these scenarios

  • GPS is turned off in the device settings.
  • Location was never recorded on the devices.  This could be the case of a new device or a device that has been restored to factory settings.

Complete Activity

  • Below code snippet shows how your activity will look after the complete implementation. Current Location is received  in the onSuccessListener added on the task object as shown below
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = findViewById(R.id.button);
        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.button:
                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) {
                   
                    return;
                }
                FusedLocationProviderClient fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
                Task task = fusedLocationProviderClient.getLastLocation();
                task.addOnSuccessListener(new OnSuccessListener() {
                    @Override
                    public void onSuccess(Location location) {

                    }
                });
                break;
        }
    }
}
  • This is how current location is fetched with FusedLocationProviderClient. If you want to learn how to display this location map you can read this.
  • We also have a amazing collection of Android Examples which will help you become a better developer. Make sure you read them

Spread knowledge

Leave a Reply

Your email address will not be published. Required fields are marked *