How to Calculate Distance Between Two GPS Coordinates in an App

A lot of fun can be done using Google Maps API. Developers, today, experiment and implement various kinds of features, including the feature to calculate the distance between two points or GPS coordinates in the Android mobile app. This can be achieved through Google Maps API. And it has made GPS Coordinate Distance Calculator easier to find how far two GPS coordinates converter is on a map.

If you are planning to develop a travel app, location tracking, taxi booking, or any on-demand delivery app, such a feature is very useful. Being a leading custom taxi booking solution developer, we have developed 50+ taxi booking apps and 40+ on-demand delivery apps. In most of these native applications, we have used this feature for real-time tracking a lot of times.

In this Android app article, we’ll develop a demo app that will display the route between two locations.

Calculate distance between two points [Google Maps API tutorial]

Here is a step by step process on how to calculate the distance between two points using Google Maps API.

hand icon Create a new project under the file menu in Android Studio.

Create a New Project

hand icon Click on next and select the MIN SDK version.

Target Android Devices

hand icon In the next tab, add a blank activity.

Add an Activity to Mobile

hand icon Lastly, customize your activity and click on finish.

Customize Activity in the App

Start Code Integration

Mainactivity

public class MainActivity extends AppCompatActivity implements ConstantInterface, OnMapReadyCallback, DirectionCallback,
    GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener{

        private SupportMapFragment mapFragment;
        private GoogleMap googleMap;
        private TextView textAddress;
        private LatLng currentLatLng;
        private GoogleApiClient googleApiClient;
        private LocationRequest locationRequest;
        private AppUtility appUtility;
        private RunTimePermission runTimePermission;

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

        @Override
        public void onStop() {
            if (googleApiClient != null && googleApiClient.isConnected()) {
                googleApiClient.disconnect();
            }
            super.onStop();
        }

        private void initControls() {
            appUtility = new AppUtility(this);
            runTimePermission = new RunTimePermission(this);
            mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
            textAddress = (TextView) findViewById(R.id.textAddress);
            textAddress.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // This is to prevent user to click on the map under the distance text.
                }
            });
            if (appUtility.checkPlayServices()) {
                    googleApiClient = new GoogleApiClient
                    .Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();
                    googleApiClient.connect();
            }
        }

        @Override
        public void onMapReady(final GoogleMap googleMap) {
            this.googleMap = googleMap;
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                googleMap.setMyLocationEnabled(true);
                googleMap.moveCamera(CameraUpdateFactory.newLatLng(currentLatLng));
                googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15 f));
            }
            googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
                @Override
                public void onMapClick(LatLng latLng) {
                    googleMap.clear();
                    googleMap.addMarker(new MarkerOptions().position(latLng));
                    GoogleDirection.withServerKey(getString(R.string.map_direction_key))
                    .from(currentLatLng)
                    .to(new LatLng(latLng.latitude, latLng.longitude))
                    .transportMode(TransportMode.DRIVING)
                    .execute(MainActivity.this);
                    showDistance(latLng);
                }
            });
        }

        @Override
        public void onDirectionSuccess(Direction direction, String ) {
        if (direction.isOK()) {
            ArrayList<LatLng> directionPositionList = direction.getRouteList().get(0).getLegList().get(0).getDirectionPoint();
            googleMap.addPolyline(DirectionConverter.createPolyline(this, directionPositionList, 1, ContextCompat.getColor(this, R.color.colorPrimary)));
            }
        }
        @Override
        public void onDirectionFailure(Throwable t) {}

        private void showDistance(LatLng latLng) {
            Location locationA = new Location("Location A");
            locationA.setLatitude(latLng.latitude);
            locationA.setLongitude(latLng.longitude);
            Location locationB = new Location("Location B");
            locationB.setLatitude(currentLatLng.latitude);
            locationB.setLongitude(currentLatLng.longitude);
            textAddress.setText("Distance : " + new DecimalFormat("##.##").format(locationA.distanceTo(locationB)) + "m");
        }

        // checking Runtime permission
        private void getPermissions(String[] strings) {
            runTimePermission.requestPermission(strings, new RunTimePermission.RunTimePermissionListener() {
                @Override
                public void permissionGranted() {
                    locationChecker(googleApiClient, MainActivity.this);
                }

                @Override
                public void permissionDenied() {
                    setResult(RESULT_CANCELED);
                    finish();
                }
            });
        }

        // Checking whether location service is enable or not.
        public void locationChecker(GoogleApiClient mGoogleApiClient, final Activity activity) {
            // Creating location request object
            locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(UPDATE_INTERVAL);
            locationRequest.setSmallestDisplacement(DISPLACEMENT);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
            builder.setAlwaysShow(true);
            PendingResult result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
        }
        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult result) {
                final Status status = result.getStatus();
                final LocationSettingsStates state = result.getLocationSettingsStates();
                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        getLocation();
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            status.startResolutionForResult(activity, 1000);
                        } catch (IntentSender.SendIntentException e) {
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        break;
                }
            }
        });

        private void getLocation() {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
                }
            }

        @Override
        public void onConnected(@Nullable Bundle bundle) {
            getPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION});
        }

        @Override
        public void onConnectionSuspended(int i) {}

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

        @Override
        public void onLocationChanged(Location location) {
            currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
            if (googleMap == null) {
                mapFragment.getMapAsync(this);
            }
        }
    }        
Copy to Clipboard

activitymain.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:id="@+id/map"
        class="com.google.android.gms.maps.SupportMapFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textAddress"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:alpha=".5"
        android:background="@color/colorPrimary"
        android:ellipsize="end"
        android:gravity="center"
        android:maxLines="2"
        android:minLines="2"
        android:padding="@dimen/scale_8dp"
        android:textColor="@android:color/white" />

    </RelativeLayout>
Copy to Clipboard

AppUtility.java

public class AppUtility implements ConstantInterface {
    private Context context;

    public AppUtility(Context context) {
        this.context = context;
    }

    // Check weather google play services is available or not.
    public boolean checkPlayServices() {
        GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
        int result = googleAPI.isGooglePlayServicesAvailable(context);

        if (result != ConnectionResult.SUCCESS) {
            if (googleAPI.isUserResolvableError(result)) {
                googleAPI.getErrorDialog((Activity) context, result, PLAY_SERVICES_RESOLUTION_REQUEST).show();
            }
            return false;
        }
        return true;
    }
}
Copy to Clipboard

RunTimePermission.java

public class RunTimePermission extends AppCompatActivity {
    private Activity activity;
    private ArrayList<PermissionBean> arrayListPermission;
    private String[] arrayPermissions;
    private RunTimePermissionListener runTimePermissionListener;
    
    public RunTimePermission(Activity activity) {
        this.activity = activity;
    }
    
    public class PermissionBean {
        String permission;
        boolean isAccept;
    }
    
    public void requestPermission(String[] permissions, RunTimePermissionListener runTimePermissionListener) {
        this.runTimePermissionListener = runTimePermissionListener;
        arrayListPermission = new ArrayList();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        for (int i = 0; i < permissions.length; i++) {
            PermissionBean permissionBean = new PermissionBean();
            if (ContextCompat.checkSelfPermission(activity, permissions[i]) == PackageManager.PERMISSION_GRANTED) {
            permissionBean.isAccept = true;
            } else{
            permissionBean.isAccept = false;
            permissionBean.permission = permissions[i];
            arrayListPermission.add(permissionBean);
            }
        }
        if (arrayListPermission.size() <= 0) {
            runTimePermissionListener.permissionGranted();
            return;
        }
        arrayPermissions = new String[arrayListPermission.size()];
        for (int i = 0; i < arrayListPermission.size(); i++) {
            arrayPermissions[i] = arrayListPermission.get(i).permission;
        }
        activity.requestPermissions(arrayPermissions, 10);
        } else {
        if (runTimePermissionListener != null) {
            runTimePermissionListener.permissionGranted();
        }
        }
    }
    
    public interface RunTimePermissionListener {
        void permissionGranted();
        void permissionDenied();
    }
    
    private void callSettingActivity() {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
        intent.setData(uri);
        activity.startActivity(intent);
    }
    
        private void checkUpdate() {
        boolean isGranted = true;
        int deniedCount = 0;
        for (int i = 0; i < arrayListPermission.size(); i++) {
        if (!arrayListPermission.get(i).isAccept) {
            isGranted = false;
            deniedCount++;
        }
        }
        if (isGranted) {
        if (runTimePermissionListener != null) {
            runTimePermissionListener.permissionGranted();
        }
        } else {
        if (runTimePermissionListener != null) {
            if  (deniedCount == arrayListPermission.size()) {
            setAlertMessage();
            }
            runTimePermissionListener.permissionDenied();
        }
        }
    }
    public void setAlertMessage() {
        AlertDialog.Builder adb;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        adb = new AlertDialog.Builder(activity, android.R.style.Theme_Material_Light_Dialog_Alert);
        } else {
        adb = new AlertDialog.Builder(activity);
        }
        adb.setTitle(activity.getResources().getString(R.string.app_name));
        String msg = "<p>Dear User, </p>" +
                    "<p>Seems like you have <b>\"Denied\"</b> the minimum requirement permission to access more features of application.</p>" +
                    "<p>You must have to <b>\"Allow\"</b> all permission. We will not share your data with anyone else.</p>" +
                    "<p>Do you want to enable all requirement permission ?</p>" +
                    "<p>Go To : Settings >> App > " + activity.getResources().getString(R.string.app_name) + " Permission : Allow ALL</p>";
        adb.setMessage(Html.fromHtml(msg));
        adb.setPositiveButton("Allow All", new AlertDialog.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            callSettingActivity();
            dialog.dismiss();
        }
        });
        adb.setNegativeButton("Cancel", new AlertDialog.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
        }
        });
        adb.create().show();
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == 10) {
        for (int i = 0; i < arrayListPermission.size(); i++) {
            arrayListPermission.get(i).isAccept = grantResults[i] == PackageManager.PERMISSION_GRANTED;
        }
        checkUpdate();
        }
    }
Copy to Clipboard

ConstantInterface.java

public interface ConstantInterface {
    int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
    int UPDATE_INTERVAL = 10000; // 10 sec
    int DISPLACEMENT = 10; // 10 meters
}
Copy to Clipboard

Strings.xml

<resources>
    <string name="app_name">MapDirectionDemo</string>
    <string name="map_direction_key">Your server Key</string>
    <!-- get your server key from google console -->
</resources>
Copy to Clipboard

Dimens.xml

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="text_22sp">22sp</dimen>
    <dimen name="scale_8dp">8dp</dimen>
</resources>
Copy to Clipboard

AndroidManiFest.xml

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />
<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="Your Android Key" />
<!-- get your android key from google console -->
Copy to Clipboard

And done!

Want to Develop an App with Google Maps API?

You have learned about how to calculate distance between gps coordinates. We will see answers to some of the most commonly asked questions.

Frequently Asked Questions

What can you do with Google Map API?

You can create a custom map, plan routes, find the distance between two or more points, create searchable maps, real-time tracking, check-in functions, measure the mileage in a straight line between two cities, are few of the things that you can do.

Can I use Google Maps in my app?

Yes, you can use Google Maps Platform products even on non-web applications. The only condition is that you adhere to the restrictions of the Google Maps Platform Terms of Service. Even if your app is a private-access application, you may still use Google Maps, Routes, and Places services.

Have you developed any apps with a distance tracking feature?

Yes, we have developed various apps that use GPS navigation, calculate distance between two GPS coordinates, real-time distance tracking, and other such features. In fact, we have developed 50+ Uber-like apps and 40+ on-demand apps. Some of them are Glovo, Bevy, Baloora, and One-8.

Conclusion

This is the simplest and easiest way to calculate distance between two latitude and longitude in Android application. The Google Maps coordinates API provides many features to developers to offer app users.

After reading this article, you might want to know about how to use Google Map Marker to show lots of data using the Android view or how to plot a current location pin on Google Map with Search Address functionality. So, if you’ve such an app idea that involves the need for Google Maps into your app, like to calculate the distance between two points, then implementing the feature of the calculating distance between two GPS coordinates is a good idea.

To implement it, you can follow our Google Maps API tutorial, or hire an Android app developer if you need technical assistance to add to your native app. Grab a free copy of code to Calculate the Distance Between Two Points Demo using Google Maps from Github.

Bhaval Patel

Written by

Bhaval Patel

Bhaval Patel is a Director (Operations) at Space-O Technologies. He has 20+ years of experience helping startups and enterprises with custom software solutions to drive maximum results. Under his leadership, Space-O has won the 8th GESIA annual award for being the best mobile app development company. So far, he has validated more than 300 app ideas and successfully delivered 100 custom solutions using the technologies, such as Swift, Kotlin, React Native, Flutter, PHP, RoR, IoT, AI, NFC, AR/VR, Blockchain, NFT, and more.