Introduction
Hi friends!! In this article, we will learn how to calculate the driving distance between two places using Google Maps Distance Matrix API in Android. In real life, many times we want to know how far away our destination or our parcel or any product etc. is from our location. We can achieve this feature by using Google Maps Distance Matrix API. We need to pass some parameters in Google API then we get the distance between two places.
Prerequisites
- Having the latest version of Android Studio
- Having a basic knowledge of Android
- Having a basic knowledge of API
Example
We are going to calculate the driving distance using the below API URL.
API URL: https://maps.googleapis.com/maps/api/distancematrix/json?origins=28.6280,77.3649&destinations=29.4168, 77.4673&mode=driving&key=YOUR_GOOGLE_MAPS_API_KEY
Generate your API key Using the following URL Generate Google Map API Key
API Response
{
"destination_addresses": [
"Nai Abadi Sisauli, Sisauli, Uttar Pradesh 251319, India"
],
"origin_addresses": [
"065, Block A, Industrial Area, Sector 62, Noida, Uttar Pradesh 201301, India"
],
"rows": [
{
"elements": [
{
"distance": {
"text": "122 km",
"value": 122484
},
"duration": {
"text": "2 hours 13 mins",
"value": 7960
},
"status": "OK"
}
]
}
],
"status": "OK"
}
Let's start with Android Studio,
Create New Android Project In Android Studio
Open your Android Studio and create a new project. Edit the project name, android language, iOS language, and platform, and click Finish button.
Add the required dependency in the build.gradle
In our project, we need to add the retrofit dependency for sending API requests and parsing JSON.
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
implementation 'com.squareup.okhttp3:okhttp:3.6.0'
Add Internet Permission into AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
Create a model class
We need to create a model class for parsing JSON. We can use this model class to easily parse the response into structured Java objects.
DistanceAndTimeResponse.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.List;
public class DistanceAndTimeResponse {
@Expose
@SerializedName("destination_addresses")
private String[] destination_addresses;
@Expose
@SerializedName("origin_addresses")
private String[] origin_addresses;
@Expose
@SerializedName("rows")
private List<Rows> rows;
@Expose
@SerializedName("status")
private String status;
public String[] getOrigin_addresses() {
return origin_addresses;
}
public void setOrigin_addresses(String[] origin_addresses) {
this.origin_addresses = origin_addresses;
}
public String[] getDestination_addresses() {
return destination_addresses;
}
public void setDestination_addresses(String[] destination_addresses) {
this.destination_addresses = destination_addresses;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public List<Rows> getRows() {
return rows;
}
public void setRows(List<Rows> rows) {
this.rows = rows;
}
public class Rows {
@Expose
@SerializedName("elements")
public List<elements> element;
public List<elements> getElement() {
return element;
}
public void setElement(List<elements> element) {
this.element = element;
}
}
public class elements {
@Expose
@SerializedName("distance")
private distance distance;
@Expose
@SerializedName("duration")
private duration duration;
public DistanceAndTimeResponse.distance getDistance() {
return distance;
}
public void setDistance(DistanceAndTimeResponse.distance distance) {
this.distance = distance;
}
public DistanceAndTimeResponse.duration getDuration() {
return duration;
}
public void setDuration(DistanceAndTimeResponse.duration duration) {
this.duration = duration;
}
}
public class distance {
@Expose
@SerializedName("text")
private String text;
@Expose
@SerializedName("value")
private String value;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
class duration {
@Expose
@SerializedName("text")
private String text;
@Expose
@SerializedName("value")
private String value;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
Create an ApiService.java class
Here, we are creating an interface and defining the API endpoint and base URL.
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface ApiService {
String BASE_URL = "https://maps.googleapis.com/maps/api/distancematrix/";
String ENDPOINT_GET_DISTANCE_FROM_TWO_LAT_LONG="json?";
@GET(ENDPOINT_GET_DISTANCE_FROM_TWO_LAT_LONG)
Call<DistanceAndTimeResponse> getDistanceAndTimeData(
@Query("origins") String origins,
@Query("destinations") String destinations,
@Query("mode") String mode,
@Query("key") String key);
}
Create a Retrofit class
The RetrofitClient.java class is used to create and manage a single instance of a Retrofit client, which helps communicate with a web API. It's designed using the Singleton pattern to ensure only one instance exists. The instance is created with a base URL and a Gson converter to handle JSON data. The class provides a method to get the Retrofit client's API interface for making API calls. This approach helps efficiently manage network requests in an Android app.
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitClient {
private static RetrofitClient instance = null;
private ApiService myApi;
private RetrofitClient() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
myApi = retrofit.create(ApiService.class);
}
public static synchronized RetrofitClient getInstance() {
if (instance == null) {
instance = new RetrofitClient();
}
return instance;
}
public ApiService getMyApi() {
return myApi;
}
}
Edit your activity_main.xml
Replace your existing code with the below code. Here, we take an input field for users to enter the latitude and longitude of the source and destination location. We take a button to perform an action when the user clicks on it and take a textview to show the output.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/source_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:gravity="center"
android:orientation="horizontal">
<EditText
android:id="@+id/source_lattitude_et1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Source Lat."
android:layout_margin="10dp"
/>
<EditText
android:id="@+id/source_longitude_et2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Source Long."
android:layout_margin="10dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/destination_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:gravity="center"
android:layout_below="@+id/source_linear_layout"
android:orientation="horizontal">
<EditText
android:id="@+id/destination_lattitude_et1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Destination Lat."
android:layout_margin="10dp"
/>
<EditText
android:id="@+id/destination_longitude_et2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Enter Destination Long."
android:layout_margin="10dp"
/>
</LinearLayout>
<Button
android:id="@+id/calculate_distance_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="Calculate Distance"
android:layout_below="@+id/destination_linear_layout"
/>
<TextView
android:id="@+id/calculated_distance_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Distance Between Source and Destination is :"
android:layout_marginTop="20dp"
android:gravity="center"
android:textSize="16sp"
android:layout_below="@+id/calculate_distance_button"
/>
</RelativeLayout>
UI Design Output
Edit MainActivity.java
Firstly we Initialize all the components such as EditText, Button, and TextView inside onCreate()
the method. Now Use a helper method to check if any EditText field is empty when the user clicks on the button. If all fields are filled then we call the getDistanceAndTime() method. This method makes an API call to the Google Maps Distance Matrix API to calculate the distance and time between two places Lat. Long. The calculated distance is displayed in a TextView. Please Make sure to replace your API Key with YOUR_GOOGLE_MAPS_API_KEY.
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private EditText sourceLatEt1,sourceLongEt2,desLatEt1,desLongEt2;
private TextView calculatedDistanceTextview;
private Button calculateDistanceBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sourceLatEt1=findViewById(R.id.source_lattitude_et1);
sourceLongEt2=findViewById(R.id.source_longitude_et2);
desLatEt1=findViewById(R.id.destination_lattitude_et1);
desLongEt2=findViewById(R.id.destination_longitude_et2);
calculateDistanceBtn=findViewById(R.id.calculate_distance_button);
calculatedDistanceTextview=findViewById(R.id.calculated_distance_textview);
calculateDistanceBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(isEditTextEmpty(sourceLatEt1)||isEditTextEmpty(sourceLongEt2)||isEditTextEmpty(desLatEt1)||isEditTextEmpty(desLongEt2)){
Toast.makeText(MainActivity.this, "Please fill all required information", Toast.LENGTH_SHORT).show();
}else{
getDistanceAndTime(sourceLatEt1.getText().toString(),sourceLatEt1.getText().toString(),desLatEt1.getText().toString(),desLongEt2.getText().toString());
}
}
});
}
/**
* This method check if edittext is empty or not.
*/
public static boolean isEditTextEmpty(EditText editText) {
return TextUtils.isEmpty(editText.getText().toString());
}
private void getDistanceAndTime(String sourceLat,String sourceLong,String destinationLat,String destinationLong) {
String sourceLatLong=sourceLat+","+sourceLong;
String desLatLong=destinationLat+","+destinationLong;
Call<DistanceAndTimeResponse> call = RetrofitClient.getInstance()
.getMyApi()
.getDistanceAndTimeData(sourceLatLong,desLatLong ,"Driving", "YOUR_GOOGLE_MAPS_API_KEY");
call.enqueue(new Callback<DistanceAndTimeResponse>() {
@Override
public void onResponse(Call<DistanceAndTimeResponse> call, Response<DistanceAndTimeResponse> response) {
if (response.body() != null) {
String travellingDistance = response.body().getRows().get(0).element.get(0).getDistance().getText();
calculatedDistanceTextview.setText(travellingDistance+"");
}
}
@Override
public void onFailure(Call<DistanceAndTimeResponse> call, Throwable t) {
Toast.makeText(getApplicationContext(), "An error has occurred", Toast.LENGTH_LONG).show();
}
});
}
}
Output
Conclusion
In this article, we have seen how to calculate the driving distance between two places using Google Map API in Android. Thanks for reading, and hope you like it. If you have any suggestions or queries about this article, please share your thoughts. You can read my other articles by clicking here.
Happy learning, friends!