[Android Example] Location Updates with FusedLocationProviderApi

In our last post we developed a app to retrieve the current location of the device on Android. While retrieving the current location can be useful in a lot of  real life scenarios sometimes it is just not enough. Thanks to Google’s FusedLocationProviderApi receiving location change updates in the app is fairly simple. In the following example we will be implementing an app which will be receiving updates on every location change.

Android Example : Requesting Location updates

This app will have a Activity with two buttons. On clicking button one the app starts receiving location updates from Google. This goes on until we click the second button.

  • First and the most obvious step would be adding the location permissions in the AndroidManifest as shown below
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  • Since we will be using Google’s FusedLocationProvider API to fetch the location updates we need to add the following the gradle file
    implementation 'com.google.android.gms:play-services-location:11.8.0'
    
  • Create a new Activity by the name MainActivity.java. Following will be the layout file for it
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:id="@+id/parent"
        android:layout_height="match_parent"
        tools:context="com.example.admin.locationupdates.MainActivity">
    
        <Button
            android:layout_width="wrap_content"
            android:text="Start"
            app:layout_constraintStart_toStartOf="@id/parent"
            app:layout_constraintEnd_toEndOf="@id/parent"
            app:layout_constraintTop_toTopOf="@id/parent"
            android:layout_marginTop="80dp"
            android:id="@+id/start_fetching"
            android:layout_height="wrap_content" />
    
        <Button
            android:layout_width="wrap_content"
            android:text="Stop"
            android:layout_marginTop="80dp"
            app:layout_constraintStart_toStartOf="@id/parent"
            app:layout_constraintEnd_toEndOf="@id/parent"
            app:layout_constraintTop_toBottomOf="@id/start_fetching"
            android:id="@+id/stop_fetching"
            android:layout_height="wrap_content" />
    
    </android.support.constraint.ConstraintLayout>
  • Now initialize the buttons declared in the layout file. Also add OnClickListeners to both the buttons
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button startFetching;

    private Button stopFetching;

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

        startFetching = findViewById(R.id.start_fetching);
        stopFetching = findViewById(R.id.stop_fetching);

        startFetching.setOnClickListener(this);
        stopFetching.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {

        switch (view.getId()) {
            case R.id.start_fetching:
                break;
            case R.id.stop_fetching:
                break;

        }
    }
}
  • To use any Google Play Services API we first need to have an object of GoogleApiClient. GoogleApiClient is the main entry for integration of Google Play services. We also need to add up listeners which would be triggered once the client is connected or disconnected to the service.
  • Our activity should implement the interfaces ConnectionCallbacks and OnConnectionFailedListener as shown below.
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
    GoogleApiClient.ConnectionCallbacks,
    View.OnClickListener {

        private GoogleApiClient googleApiClient;

        private Button startFetching;

        private Button stopFetching;

        private boolean isConnected;

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

            startFetching = findViewById(R.id.start_fetching);
            stopFetching = findViewById(R.id.stop_fetching);

            startFetching.setOnClickListener(this);
            stopFetching.setOnClickListener(this);

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

        public void onStart() {
            super.onStart();
            googleApiClient.connect();
        }

        public void onStop() {
            super.onStop();
            googleApiClient.disconnect();

        }

        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

        }

        @Override
        public void onConnected(@Nullable Bundle bundle) {
            isConnected = true;
        }

        @Override
        public void onConnectionSuspended(int i) {
            isConnected = false;
        }
    }
  • Below you see we have initialized an object of LocationRequest. This object is used to define the quality of service parameters for request sent to FusedLocationProviderApi.
  • The frequency and accuracy of the location updates you receive are completely dependent on the parameters you specify along with the location request object. Like in this example we specify the smallest displacement as 10 meters (Which means that we will receive location update only if there is a displacement of more than 10 meters). Similarly we set the accuracy of location updates to high.
public class MainActivity extends AppCompatActivity implements GoogleApiClient.OnConnectionFailedListener,
    GoogleApiClient.ConnectionCallbacks,
    View.OnClickListener {

        private GoogleApiClient googleApiClient;

        private LocationRequest locationRequest;

        private static final int MIN_DISPLACEMENT = 10;

        private static final int LOCATION_REQUEST_CODE = 101;

        private Button startFetching;

        private Button stopFetching;

        private boolean isConnected;

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

            startFetching = findViewById(R.id.start_fetching);
            stopFetching = findViewById(R.id.stop_fetching);

            startFetching.setOnClickListener(this);
            stopFetching.setOnClickListener(this);

            locationRequest = new LocationRequest();
            locationRequest.setSmallestDisplacement(MIN_DISPLACEMENT);
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        }
    }

 

  • Now comes the most important part- requesting for location change updates. Before requesting we need to define our callback listener which will be triggered every time a new location is detected.
LocationListener locationListener = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {

        Toast.makeText(MainActivity.this, location.getLatitude() + "," + location.getLongitude(), Toast.LENGTH_SHORT).show();

    }
};
  • Now when the button is clicked we should request for location updates. This is done by a call to FusedLocationProviderAPI as shown below
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, locationListener);
  • It takes in three parameters. First is GoogleApiClient object(Which is the main entry point of Google PlayServices integration), second is LocationRequest object which define the frequency and accuracy of updates received as explained above. Third is the listener interface which is triggered every time there is a update in user location

Please note that if you are developing this for Marshmallow or above you need to add runtime permission for location

  • Now we add this code to the OnClick listeners as shown below
@Override
public void onClick(View view) {

    switch (view.getId()) {
        case R.id.start_fetching:
            if (isConnected) {
//This condition check if the user has already been granted location permission or not.
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
//We come only if the location permission is not granted. Hence we request for permission by displaying a dialog.
                    ActivityCompat.requestPermissions(this, new String[] {
                        Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION
                    }, LOCATION_REQUEST_CODE);
                    return;
                }
               /*
                We come here only if the permission is already granted .
                Here we will actually request for the location
                */
                LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, locationListener);
            } else
                Toast.makeText(this, "Connection Failed", Toast.LENGTH_SHORT).show();
            break;

        case R.id.stop_fetching:
            LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, locationListener);
            break;

    }
}
  • The complete activity will look like this

 

location_updates

If you want to fetch only the current location using Google APIs. Refer this

Conclusion

The above example is the complete solution of how to fetch location updates inside you android application. You can show the fetched locations on a map with the this example.

If you want to show the fetched locations on a Google map. Please refer this article

One thought on “[Android Example] Location Updates with FusedLocationProviderApi

Leave a comment