Measure Your Distance on Map

In this tutorial we will learn how to implement Google Maps in our application, how to measure the distance and how to visualize it on the map.

With the Maps SDK for Android, we can add maps based on Google Maps data to our application.

The API automatically handles access to Google Maps servers, data downloading, map display, and response to map gestures. We can also use API calls to add markers, polygons, and overlays to a basic map, and to change the user’s view of a particular map area. These objects provide additional information for map locations, and allow user interaction with the map. The API allows us to add this graphics to a map

  • Icons anchored to specific positions on the map (Markers).
  • Sets of line segments (Polylines).
  • Enclosed segments (Polygons).
  • Bitmap graphics anchored to specific positions on the map (Ground Overlays).
  • Sets of images which are displayed on top of the base map tiles (Tile Overlays).

Step 1 – Get Google Maps API Key

Before we run our application, we need a Google Maps API key. We will cheat a little bit to have an easier life 🙂 First we will add a MapActivity to our application, even if we won’t need it later. We do this, because Android Studio will generate for us the needed link, where we can request the API key. To add a new MapActivity, click with the right button of your mouse on the package, then New – Activity – Gallery and finally Google Maps Activity.

Step 2.1 – Check out the generated code

Android Studio has generated the google_maps_api.xml file as well, what is located in the res – values folder. This xml file contains the string, where we will have our API Key. This string is called from the AndroidManifest.xml.


AndroidManifest.xml

The have the current position of our phone, we need to implement two permissions. In our case it is automatically added during the generation of the MapActivity.

Step 2.2 – Check out the generated code

Android Studio has generated the needed dependencies also, what we can find in build.gradle.  

implementation ‘com.google.android.gms:play-services-location:17.0.0’
implementation ‘com.google.android.gms:play-services-maps:17.0.0’

Step 3

In google_maps_api.xml we have a link, what looks like this: https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=5A:D2:…..

Copy this link to your browser, open it. Here we will create a new project.

Step 4

…and here it is. Copy the key, and you can close the pop-up window. In the google_maps_api.xml change the string “YOUR_KEY_HERE” with the API Key. Here we will create a new project.

Step 5 – activity_main.xml

Our user interface will again very simple. It will contain 2 Buttons, a Start and a Reset button, and at the top the TextView, where we will see the distance of our movement.

This Views will be above of a Fragment, what will hold our Google Map.


activity_main.xml

Step 6 – LocationCalculations::class

As you know, we will have a TextView about the distance, and a Google Map to show our root there. This class will be the responsible to calculate the distance, and summarize the points of the root. Before the implementatio we should talk about MutableLiveData and PolylineOptions.

MutableLiveData

LiveData is part of Android Architecture Components released by Google. It is an Observable(it follows observer pattern) class that holds data of type that you specify.

MutableLiveData is a subclass of LiveData which is used for some of it’s properties (value/postValue) and using these properties we can easily notify the ui when onChange() is called.

Only using LiveData object we can’t do this. So, we have to convert the target object to MutableLiveData/MediatorLiveData for notifying on each time of changing data.

This means, that we can observe the value of the MutableLiveData with obeservers. When the data is changed, then all of the observers going to be called and notified.

PolylineOptions

The PolylineOptions going to hold the path of our movement. It means we will collect a LatLng object, what has as attribute the latitude and the longitude. Every time, when you get a new location from the Callback, then this coordinate will be stored in our PolylineOptions.

The get together the MutableLiveData and the PolylineOptions, we will post the value of the PolylineOptions to a MutableLiveData. Later on we will have an observer in the MainActivity::class, what will be always notified when new location is available.

The result will be on the map, that it will be refreshed and the line of our path will be extended with the new coordinate.

Distance calculataion

To have always the valid distance we have to know our location before our last location. We need it, because we have to coordinates to calculate the distance between them. This distance will be summarized also in a MutableLiveData. In the MainActivity we will have again an observer, and this observer will modify always the TextView to have the current distance visible.

Let’s see the code of the LocationCalculations::class

Step 7 – MainActivity::class

Our last step is the MainActivity::class. This Activity will handle and hold the whole process. But first we have to clarify some things.

getMapAsync()

Sets a callback object which will be triggered when the GoogleMap instance is ready to be used.

Note
  • This method must be called from the main thread.
  • The callback will be executed in the main thread.
  • In the case where Google Play services is not installed on the user’s device, the callback will not be triggered until the user installs it.

As we mentiond before, we have to have the ACCESS_FINE_LOCATION permission to get to know where we are on the map. Because this is an information about the users, we have to get the permission from them.

In this app directly in the onCreate() method we will ask the user, in case if the permission is not granted yet.
checkSelfPermission()

This method checks whether your app has a given permission and whether the app op that corresponds to this permission is allowed.
The returned value is an integer, what can be

  • PERMISSION_GRANTED
  • PERMISSION_DENIED
  • PERMISSION_DENIED_APP_OP
shouldShowRequestPermissionRationale()

Gets whether you should show UI with rationale for requesting a permission. You should do this only if you do not have the permission and the context in which the permission is requested does not clearly communicate to the user what would be the benefit from granting this permission.

To get our current position we have to implement FusedLocationProviderClient.

Using the Google Play services location APIs, our app can request the last known location of the user’s device. In most cases, we 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.

requestLocationUpdates (LocationRequest request, LocationCallback callback, Looper looper)

Requests location updates with a callback on the specified Looper thread.

LocationRequest

LocationRequest objects are used to request a quality of service
for location updates

interval: Set the desired interval for active location updates, in milliseconds

fastestInterval: Explicitly set the fastest interval for location updates, in milliseconds.

priority: The priority of the request is a strong hint to the LocationClient for which location sources to use. For example, PRIORITY_HIGH_ACCURACY is more likely to use GPS

LocationCallback

Used for receiving notifications from the FusedLocationProviderApi when the device location has changed or can no longer be determined.

Looper

This class used to run a message loop for a thread.

Let’s see our last code, what is the MainActivity::class

Questions

I hope the description was understandable and clear. But if you have still questions, then leave me comments below! 😉

Have a nice a day! 🙂

 


 

Follow and like us:

Leave a Reply

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