Main navigation

Google Maps Draw Route between two points using Google Directions in Google Map Android API V2

adsense

Pre-requisites:

1) Android Studio installed on your PC (Unix or Windows). You can learn how to install it here .
2) A real time android device (Smartphone or Tablet) configured with Android Studio. .
3) A basic knowledge of Android lifecycle and different classes & functions used in Android Studio.

Before going through this post we will suggest you to first have a look at our post on How to get current location in Android Google Map. That information (inside link) will be used in this post.

Now let’s make it. We hope you would have already made an App to display current user location. So we are not repeating that part now.

Creating new project

Please follow following steps:

  1. Open Android Studio and make a new project with name “Google Maps Draw Route” and company domain application.example.com (I used my company domain i.e androidtutorialpoint.com. Similarly you can use yours).
  2. Click Next and choose android version Lollipop. Again Click Next and Choose Google Maps Activity (as shown in following pic).
  3. Google_Map_Activity

  4. Leave all things remaining same and Click Finish.

Now you will be able to see three files:

  1. google_maps_api.xml (…/GoogleMapsDrawRoute/app/src/debug/res/values/google_maps_api.xml)
  2. MapsActivity.java (…/GoogleMapsDrawRoute/app/src/main/java/com/androidtutorialpoint/googlemapsdrawroute/MapsActivity.java)
  3. AndroidManifest.xml ( …/GoogleMapsDrawRoute/app/src/main/AndroidManifest.xml)

Configuring Google Play Services

Open google_maps_api.xml. Here you will find a lot of information along with a link. Copy-Paste this link in your web browser. Make a Gmail account also through which you will configure google play services.

MapApp_key_1

Now at the browser choose “Create New Project” and Click Continue. Following screen will be displayed:

MapApp_key_2

Click on Go to credentials. Below screen will appear.

MapApp_key_3

Create your key by clicking Create. Now a key will be created that you shall copy and paste in google_maps_api.xml. Copy paste it in place where YOUR_KEY_HERE is written:

Code inside google_maps_api.xml is complete.

google_maps_api.xml

<resources>
    <!--
    TODO: Before you run your application, you need a Google Maps API key.

    To get one, follow this link, follow the directions and press "Create" at the end:

    https://console.developers.google.com/flows/enableapi?apiid=maps_android_backend&keyType=CLIENT_SIDE_ANDROID&r=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx%com.androidtutorialpoint.googlemapsapp

    You can also add your credentials to an existing key, using this line:
    xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx;com.androidtutorialpoint.googlemapsapp

    Alternatively, follow the directions here:
    https://developers.google.com/maps/documentation/android/start#get-key

    Once you have your key (it starts with "AIza"), replace the "google_maps_key"
    string in this file.
    -->
    <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false">LVwrKoLOEMgwUBXGiut0bkFhoAjOiaVemoMlymg</string>     
</resources>

Also one more thing to do here is to enable corresponding directions API. In the following image click Google Maps Directions API and then enable it:

Google Maps Distance Calculator

Code Inside AndroidManifest.xml:

If you go inside AndroidManifest.xml then this key will be displayed in meta tags. Here you need to add permissions for accessing location of device. The required permission should be as follows:

ACCESS_NETWORK_STATE – To check network state i.e if we are connected to any network or not.
INTERNET – If we are connected to Internet or not.
ACCESS_COARSE_LOCATION – To determine user’s location using WiFi and mobile. It will give us an approximate location.
ACCESS_FINE_LOCATION – To determine user’s location using GPS. It will give us precise location.
OpenGL ES V2 – Required for Google Maps V2

AndroidManifest.xml

  
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.androidtutorialpoint.googlemapsdrawroute"
          xmlns:android="https://schemas.android.com/apk/res/android">

    <!--
         The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
         Google Maps Android API v2, but you must specify either coarse or fine
         location permissions for the 'MyLocation' functionality. 
    -->
    <uses-permission android:name="com.androidtutorialpoint.mymapsappsdirection.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!--
             The API key for Google Maps-based APIs is defined as a string resource.
             (See the file "res/values/google_maps_api.xml").
             Note that the API key is linked to the encryption key used to sign the APK.
             You need a different API key for each encryption key, including the release key that is used to
             sign the APK for publishing.
             You can define the keys for the debug and release targets in src/debug/ and src/release/. 
        -->
        <meta-data
            android:name="com.google.android.geo.API_KEY"
            android:value="@string/google_maps_key"/>

        <activity
            android:name=".MapsActivity"
            android:label="@string/title_activity_maps">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>


Code inside MapsActivity.java:

This is heart of our code. We will divide this code into parts and debug it one by one. Here we won’t discuss code related to getting current user location. You can get that information here.

1) Setting OnClickListener:

  // Setting onclick event listener for the map
        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

            @Override
            public void onMapClick(LatLng point) {

                // Already two locations
                if (MarkerPoints.size() > 1) {
                    MarkerPoints.clear();
                    mMap.clear();
                }

                // Adding new item to the ArrayList
                MarkerPoints.add(point);

                // Creating MarkerOptions
                MarkerOptions options = new MarkerOptions();

                // Setting the position of the marker
                options.position(point);

                /**
                 * For the start location, the color of marker is GREEN and
                 * for the end location, the color of marker is RED.
                 */
                if (MarkerPoints.size() == 1) {
                    options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
                } else if (MarkerPoints.size() == 2) {
                    options.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
                }


                // Add new marker to the Google Map Android API V2
                mMap.addMarker(options);

                // Checks, whether start and end locations are captured
                if (MarkerPoints.size() >= 2) { 
                    LatLng origin = MarkerPoints.get(0);
                    LatLng dest = MarkerPoints.get(1);

                    // Getting URL to the Google Directions API
                    String url = getUrl(origin, dest);
                    Log.d("onMapClick", url.toString());
                    FetchUrl FetchUrl = new FetchUrl();

                    // Start downloading json data from Google Directions API
                    FetchUrl.execute(url);
                    //move map camera
                    mMap.moveCamera(CameraUpdateFactory.newLatLng(origin));
                    mMap.animateCamera(CameraUpdateFactory.zoomTo(11));
                }

            }
        });

Above code will be executed as soon as user tap on Android screen. It will be used to place marker at the points between which path will be drawn. Coordinates of tapped points will be accessed and stored using MarkerPoints.get() and LatLng origin respectively.Url will be fetched and implemented using Async Task FetchUrl.

2) Async Task:

AsyncTask is an abstract class provided by Android which helps us to use the UI thread properly. This class allows us to perform long/background operations and show its result on the UI thread without having to manipulate threads. You can get more information about it here. Here doInBackground task will be implemented in background and onPostExecute will be shown on GUI.

  // Fetches data from url passed
    private class FetchUrl extends AsyncTask<String, Void, String> {

        @Override
        protected String doInBackground(String... url) {

            // For storing data from web service
            String data = "";

            try {
                // Fetching the data from web service
                data = downloadUrl(url[0]);
                Log.d("Background Task data", data.toString());
            } catch (Exception e) {
                Log.d("Background Task", e.toString());
            }
            return data;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);

            ParserTask parserTask = new ParserTask();

            // Invokes the thread for parsing the JSON data
            parserTask.execute(result);

        }
    }
  

downloadUrl is used to fecth url from web service and result is parsed using ParserTask (Async Task).

3) Code inside downloadUrl:

  private String downloadUrl(String strUrl) throws IOException {
        String data = "";
        InputStream iStream = null;
        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL(strUrl);

            // Creating an http connection to communicate with url
            urlConnection = (HttpURLConnection) url.openConnection();

            // Connecting to url
            urlConnection.connect();

            // Reading data from url
            iStream = urlConnection.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));

            StringBuffer sb = new StringBuffer();

            String line = "";
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            data = sb.toString();
            Log.d("downloadUrl", data.toString());
            br.close();

        } catch (Exception e) {
            Log.d("Exception", e.toString());
        } finally {
            iStream.close();
            urlConnection.disconnect();
        }
        return data;
    }
  

Data returned from web will be in json format which user can get using HttpURLConnection. You can get more information about how to get data over web here. So this task will return json data returned from web.

4) Code inside Parser Task:

Define a new class with the name ParserTask which will parse the Json data retuned by downloadUrl.

private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {

        // Parsing the data in non-ui thread
        @Override
        protected List<List<HashMap<String, String>>> doInBackground(String... jsonData) {

            JSONObject jObject;
            List<List<HashMap<String, String>>> routes = null;

            try {
                jObject = new JSONObject(jsonData[0]);
                Log.d("ParserTask",jsonData[0].toString());
                DataParser parser = new DataParser();
                Log.d("ParserTask", parser.toString());

                // Starts parsing data
                routes = parser.parse(jObject);
                Log.d("ParserTask","Executing routes");
                Log.d("ParserTask",routes.toString());

            } catch (Exception e) {
                Log.d("ParserTask",e.toString());
                e.printStackTrace();
            }
            return routes;
        }

        // Executes in UI thread, after the parsing process
        @Override
        protected void onPostExecute(List<List<HashMap<String, String>>> result) {
            ArrayList<LatLng> points;
            PolylineOptions lineOptions = null;

            // Traversing through all the routes
            for (int i = 0; i < result.size(); i++) {
                points = new ArrayList<>();
                lineOptions = new PolylineOptions();

                // Fetching i-th route
                List<HashMap<String, String>> path = result.get(i);

                // Fetching all the points in i-th route
                for (int j = 0; j < path.size(); j++) {
                    HashMap<String, String> point = path.get(j);

                    double lat = Double.parseDouble(point.get("lat"));
                    double lng = Double.parseDouble(point.get("lng"));
                    LatLng position = new LatLng(lat, lng);

                    points.add(position);
                }

                // Adding all the points in the route to LineOptions
                lineOptions.addAll(points);
                lineOptions.width(10);
                lineOptions.color(Color.RED);

                Log.d("onPostExecute","onPostExecute lineoptions decoded");

            }

            // Drawing polyline in the Google Map for the i-th route
            if(lineOptions != null) {
                mMap.addPolyline(lineOptions);
            }
            else {
                Log.d("onPostExecute","without Polylines drawn");
            }
        }
    }

In the above code doInBackground will actually parse the data and onPostExecute will draw route on Google Maps.

5) Parsing data:

Make a separate java class with the name DataParser at the path: GoogleMapsDrawRoute/app/src/main/java/com/androidtutorialpoint/googlemapsdrawroute/

DataParser class

public class DataParser {

    /** Receives a JSONObject and returns a list of lists containing latitude and longitude */
    public List<List<HashMap<String,String>>> parse(JSONObject jObject){

        List<List<HashMap<String, String>>> routes = new ArrayList<>() ;
        JSONArray jRoutes;
        JSONArray jLegs;
        JSONArray jSteps;

        try {

            jRoutes = jObject.getJSONArray("routes");

            /** Traversing all routes */
            for(int i=0;i<jRoutes.length();i++){
                jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs");
                List path = new ArrayList<>();

                /** Traversing all legs */
                for(int j=0;j<jLegs.length();j++){
                    jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps");

                    /** Traversing all steps */
                    for(int k=0;k<jSteps.length();k++){
                        String polyline = "";
                        polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points");
                        List<LatLng> list = decodePoly(polyline);

                        /** Traversing all points */
                        for(int l=0;l<list.size();l++){
                            HashMap<String, String> hm = new HashMap<>();
                            hm.put("lat", Double.toString((list.get(l)).latitude) );
                            hm.put("lng", Double.toString((list.get(l)).longitude) );
                            path.add(hm);
                        }
                    }
                    routes.add(path);
                }
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }catch (Exception e){
        }


        return routes;
    }


    /**
     * Method to decode polyline points
     * Courtesy : https://jeffreysambells.com/2010/05/27/decoding-polylines-from-google-maps-direction-api-with-java
     * */
    private List<LatLng> decodePoly(String encoded) {

        List<LatLng> poly = new ArrayList<>();
        int index = 0, len = encoded.length();
        int lat = 0, lng = 0;

        while (index < len) {
            int b, shift = 0, result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lat += dlat;

            shift = 0;
            result = 0;
            do {
                b = encoded.charAt(index++) - 63;
                result |= (b & 0x1f) << shift;
                shift += 5;
            } while (b >= 0x20);
            int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
            lng += dlng;

            LatLng p = new LatLng((((double) lat / 1E5)),
                    (((double) lng / 1E5)));
            poly.add(p);
        }

        return poly;
    }
}
  

In the above code, I have added comments wherever required. Still if you have doubt then please ask in comments.

6) Draw route on google maps:

Route is drawn using Google Maps polyline. Add following code in onPostExecute :

onPostExecute

        @Override
        protected void onPostExecute(List<List<HashMap<String, String>>> result) {
            ArrayList<LatLng> points;
            PolylineOptions lineOptions = null;

            // Traversing through all the routes
            for (int i = 0; i < result.size(); i++) {
                points = new ArrayList<>();
                lineOptions = new PolylineOptions();

                // Fetching i-th route
                List<HashMap<String, String>> path = result.get(i);

                // Fetching all the points in i-th route
                for (int j = 0; j < path.size(); j++) {
                    HashMap<String, String> point = path.get(j);

                    double lat = Double.parseDouble(point.get("lat"));
                    double lng = Double.parseDouble(point.get("lng"));
                    LatLng position = new LatLng(lat, lng);

                    points.add(position);
                }

                // Adding all the points in the route to LineOptions
                lineOptions.addAll(points);
                lineOptions.width(10);
                lineOptions.color(Color.RED);

                Log.d("onPostExecute","onPostExecute lineoptions decoded");

            }

            // Drawing polyline in the Google Map for the i-th route
            if(lineOptions != null) {
                mMap.addPolyline(lineOptions);
            }
            else {
                Log.d("onPostExecute","without Polylines drawn");
            }
        }  

Finally in the above code points are fetched from result and drawn on Google Map.ArrayList points is used to store position on Google Map. Route is drawn using google maps polyline lineOptions.addAll(points).

You can see full code in following files:

MapsActivity.java
DataParser.java
google_maps_api.xml
AndroidManifest.xml

So finally our app is complete. We would suggest you to turn on GPS and Internet Connection. Run this route maker on any real android device. It will first display your location. Now tap on any two locations and it will show route between them.



What’s Next

You can experiment with different locations around world and even make a list of bars or restaurants near you and draw path between them. Moreover you can learn How to search nearby locations and add marker on places like Restaurants, Schools, Hospitals etc. in Google Maps.

Thanks for reading guys. If you have any doubt or suggestions then please comment. Don’t forget to subscribe our blog for latest android tutorials. Also do Like our Facebook Page or Add us on Twitter. Happy Coding 🙂

You can download full code below


Android Tutorial Point Download Now





Reader Interactions

Comments

    • Hi Paul,

      Actually we want to make it as simple as possible for the reader that is why we make a single class, but still your point is also valid. We will try to take care of it in next post. Thanks for your suggestion :).

  1. Hi. thank you for nice tutos.
    Please, Have you a tuto which find places nearby in Google Maps using Google Places API ?

    Regards,

    • Thanks Herve for the nice words. 🙂

      Yes we will going to make next tutorial on how to find nearby places on Google Maps. Thanks for suggestion. Stay tuned.

  2. hello, i want to know if you or somebody can help me, i need to put the markers when the map is ready, no when i click on the map, i tried to puting the code in onMapReady but it doesn’t work (sorry for my english is bad.) thank you.

    • That you can easily do. Just remove the logic of OnClickListener and call that code by default. OnMapReady() will be called when map is ready and at that moment you can add marker. All the best 🙂

    • This error will come when you are not tapping on map to add marker. MarketPoint is simply working as a memory for pointer info.

    • That is just a URL function. I would suggest you to Download code as above and run it. It will work for sure. All the best 🙂

  3. Hey
    i have an issue…the application is crashing while starting..there are no errors in android studio :/
    plz help

  4. Hi i run above code. But does not exist polyline.
    Do you know what is the problem?
    return status “ZERO_RESULTS”

    [Android Debug Log]
    11-09 10:33:01.255 32202-32202/example.com.directions D/onMapClick: https://maps.googleapis.com/maps/api/directions/json?origin=37.594766535524,127.02063605189323&destination=37.55151711450724,127.10569862276316&sensor=false

    [result]
    {
    “geocoded_waypoints” : [ {}, {} ],
    “routes” : [],
    “status” : “ZERO_RESULTS”
    }

  5. Hey everyone, I want to get latitude and longitude from database then draw route between the points. I have fetched lat lng from database but the problem is that I dont know where to set these coordinates as origin and destination. Can someone help me with that ??

  6. i want to know how to do it by this using current location and destination
    https://test.isuraksha.in/isuraksha/test/history/ please see this link
    select device like select id=10 selected device after that above api to draw polyline
    fetch device location for selected device and then draw polyline on google maps, show start point and end point,
    distance travelled from data

  7. You have written very nice code but there is a simple mistake in your code.Your code is only for single route and if route is more than one that it won’t work.Please rectify that.

  8. hi thanks for the useful code and i’m getting error while running the program as polyline is unable to draw because of (Attempt to invoke interface method ‘int java.util.List.size()’ on a null object reference).

  9. Hi thanks for the code and i am unable to draw polyline and here is my error (Attempt to invoke interface method ‘int java.util.List.size()’ on a null object reference).

    Respond me ASAP.

  10. Hello,

    I want the current location to be the default first marker instead of separately marking another one on the map. Can you suggest how it can be done?

    Thanks

  11. Where do I find the API Server Key option? I don’t see the screenshot that you posted anywhere that says Server Key in the UI of add credentials. I only see API Key creation option. Please help.

  12. can you just tell me how to do these with retrofit library? i am a new android learner and i made the project of getting near by place search and current location using your retrofit tutorial and now i want to add these and also distance calculator.

  13. It’s showing error at “mMap.addPolyline(lineOptions);” in ParserTask as can not resolve symbol ‘mMap’ .plz help me

  14. hi,
    your tutorial is very good and easy to understand. I have a doubt, how we can calculate the distance between current location and user input location using google map . In your project you worked with only map click listener . please help me

  15. Hi, thanks for the awesome tutorial! I am having some trouble with my MarkerPoints. They stay red and I get the error “cannot find symbol variable MarkerPoints”. I am not really sure how to fix it. If I ALT-ENTER I get several options: Create class, create field, create inner class, create local variable, create parameter and rename reference.

    What can I do to fix this? Thanks so much 🙂 !

  16. I am using this part as fragment in my app, but still my app get closed even though i have onResume() and on Pause() methods. I could see 2 different markers but it does’t draw any line and my app closes down? Anybody can explain why?

  17. Hi ,Thanks for this tutorial (y).
    I need to ask you about things , I wante to use tow points ( Input)
    Example :
    String altitude1=”12.45656″ // location 1
    String langtitude1=14.458″ //
    String altitude2=”30.45656″ // location2
    String langtitude2=9.458″ //

    How to do for Draw Route between these two points ?

  18. Hii Thanks for the tutorial…
    I am stuck in my application. I want to draw the route between more than two loactions. can you please help me….

  19. Hi my Friend,
    You’re the men, thank you very much, nice tutorial.
    Folks if you’re working with waypoints, make SURE that you put the line in DataParser.java
    routes.add(path)
    outside of the
    for(int j=0;j<jLegs.length();j++) loop, because if youre working with n waypoints it generates a n routes with the same information, make your app slow, just a little advice 😉

  20. Hi, Thanks.. But there are few faults as other people have commented. Polylines is not working and if I tap in more than 1 place the app is stopping. Please suggest.

  21. Multiple Points Code Please having Dex issue with 5 points passed by iteration in ArrayList. as origin and dest values.

Leave a Reply

Advertisment ad adsense adlogger