Home Tutorials Hints & Tips

Android FusedLocationProviderAPI Deprecated - How to use the FusedLocationProviderClient - Part 4

This series of tutorials shows you how to use the FusedLocationProviderClient in place of the deprecated FusedLocationProviderAPI to receive location updates to your Android device. This tutorial is written in Java and a Kotlin version will be available soon.


In part 3, we looked at how the get the last known location of the device and deal with the runtime permissions. In this part, we look at how to dynamically update the location of the device.


We first need to create three java members.


private LocationRequest locationRequest;

private LocationCallback locationCallback;

private boolean updatesOn = false;


The locationRequest member is needed to configure parameters for the Fused Location Provider such as the interval we will access the location sensors.


The locationCallback used for receiving notifications from the Fused Location Provider when the device location has changed or can no longer be determined.


Finally, we will set a boolean flag to indicate whether location updates are turned on or off.


The next task is to configure the locationRequest:


locationRequest = new LocationRequest();

locationRequest.setInterval(7500); //use a value fo about 10 to 15s for a real app

locationRequest.setFastestInterval(5000);

locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);


First, set locationRequest as an object of the LocationRequest class. We then set the interval by which we wish to acquire the location from the Fused Location Provider. Here, I set the interval to 7500ms to speed up testing. However, the shorter the interval the more battery power will be used and so a value of 10000 to 15000ms may be better for a real app. We can also set a fastest interval. If set, our app can check to see if another app has generated a location that we can use. This consumes no power and so the interval can be much shorter. A period of about 5000ms is about right. We also need to set an initial locationRequest priority. The setPriority method defines the type of sensor used. Balanced Power Accuracy means that the location will be found by using WiFi and Cell Tower triangleization. PRIORITY_HIGH_ACCURACY uses the GPS but also uses more battery power than WiFi and Cell Tower triangleization. We can also go onto add setPriority code into the onclick method for the switchGpsBalanced ToggleButton.


switchGpsBalanced.setOnClickListener(new View.OnClickListener() {

@Override

   public void onClick(View v) {

      if (switchGpsBalanced.isChecked()) {

         //using GPS only

         sensorType.setText("GPS");

         locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

      } else {

          //using balanced power accuracy

sensorType.setText("Cell Tower and WiFi");          locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

       }

    }

});


The next task is to create to location Callback. This is coded in the onCreate method and will be called each time the location changes. We need to override the onLocationResult method and we will simply update the User Interface (UI) with the location. The UI update code can be copied from the code block within the onSuccess listener from part 4.


locationCallback = new LocationCallback() {

@Override

   public void onLocationResult(LocationResult locationResult) {

      super.onLocationResult(locationResult);

      for (Location location : locationResult.getLocations()) {

         //Update UI with location data

         if (location != null) {

            latitude.setText(String.valueOf(location.getLatitude()));

            longitude.setText(String.valueOf(location.getLongitude()));

           accuracy.setText(String.valueOf(location.getAccuracy()));

           if (location.hasAltitude()) {

               altitude.setText(String.valueOf(location.getAltitude()));

           } else {

               altitude.setText("No altitude available");

           }

           if (location.hasSpeed()) {

              speed.setText(String.valueOf(location.getSpeed()) + "m/s");

           } else {

              speed.setText("No speed available");

           }

         }

      }

   }

};


We can then add code to turn on and turn off the location updates. We do not want any app to request updates in a pause state. This is bad practice. Therefore, we can use the Android Activity Lifecycle to turn location update on and off in the appropriate state. The diagram below shows the Android Activity Lifecycle.

The Android Activity Lifecycle


You will see that onResume is called after onCreate and also when the app is resumed. It makes sense to turn on location updates here. Also onPause is called before the app is paused and stopped. Therefore, it makes sense to stop the location updates here.


When overriding the onResume methods we need to check that location updates are enabled via the toggle button and if so, start the updates. We can create a method to do this:


@Override

protected void onResume() {

   super.onResume();

   if (updatesOn) startLocationUpdates();

}


We will stop the location updates by overriding the onPause method.


@Override

protected void onPause() {

   super.onPause();

   stopLocationUpdates();

}


The method startLocationUpdates is below:


private void startLocationUpdates() {

   if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {

    fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);

   } else {

       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

          requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSION_REQUEST_FINE_LOCATION);

       }

   }

}

Location updates are enabled with the following command:


fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, null);


It will need a permission check and we can simply reuse the code from part 3. The locationRequest and locationCallback are passed to the requestLocationUpdates method. The final parameter is the looper and this is set to null to ensure updates are run on the current thread.


The method stopLocationUpdates is below:


private void stopLocationUpdates() {

   fusedLocationProviderClient.removeLocationUpdates(locationCallback);

}


The startLocationUpdates and stopLocationUpdates methods need to be added to the locationOnOff onClick method. Also add code here to set the updatesOn Boolean flag to true or false.


locationOnOff.setOnClickListener(new View.OnClickListener() {

   @Override

   public void onClick(View v) {

      if (locationOnOff.isChecked()) {

         //location updates on

         updatesOnOff.setText("On");

         updatesOn = true;

         startLocationUpdates();

      } else {

         //location updates off

         updatesOnOff.setText("Off");

         updatesOn = false;

         stopLocationUpdates();

      }

   }

});


This is all the coding needed for part 4 and a screenshot of the output is below:


FusedLocationProviderClient Image


After this tutorial your MainActivity.java file should look like the one below:




Download Download project files

Privacy and Cookies Disclaimer Copyright
© 2015 - 2018 North Border Tech Training All rights reserved