Drawing Route Between Two Points Using Google Map

Subba Raju
9 min readMay 29, 2018

--

Hello Everyone, In this post, we will discuss about creating a Today we are going to learn How To Draw Route Between Two Points Using Google Map.

1. To do Google map integration in our app we need Google Map API Key
So first we need to go to
https://developers.google.com/maps/documentation/android-api/signup
Click the Get A Key button, It will open dialog like

Create a New Project , click Next , Then we will get an API Key like

2. If we want to Restrict the Key usage Click API Console ,Otherwise click DONE.

In the API Console we can Restrict the Key usage only for Websites, Android apps, IOS apps etc.

If we click API Console then it will redirect to one more page.
There we can see the Creation date, Created by etc. We can choose the API key where we should restrict, Click the Android apps radio button.

Now if we want to Restrict usage to your android apps we must add Package name and fingerprint.

3.We will get the package name from Androidmanifest.xml file.

Fingerprint means SHA-1 certificate.
Now go to Android studio open Gradle file which is at right corner side click that.

There we can see two points.

  1. Your project name gradle
  2. App gradle

Click the app gradle file, then it will open two points

  1. Tasks
  2. Run Configurations

Now click the Tasks file, then it will open 5 points in that click “android” again it will open
Now double click the “signingReport” like

Now we can see the SHA-1 Certificate, copy that SHA-1 and paste in SHA-1 fingerprint box as shown in above image.

At last click the Save button.

4. Now create a New Android Project with the name as we want and company domain etc.

Click Next then choose Android Version Lollipop, Click Next and choose Google Map Activity as shown below. Now click next and finish button.

5. After creating project we should see some files

  1. MapsActivity.java
  2. Activity_maps.xml
  3. google_maps-api.xml

6. First we should change the google_map_api.xml
In this file we should add Google API Key which we created before.

<string name=”google_maps_key” templateMergeStrategy=”preserve” translatable=”false”>API Key</string>

7. Now we need to change in Androidmanifest.xml file

7.1. Internet Connection — To communicate with api and to get location
7.2. READ_GSERVICES — Whenever an app want to use the Google Service Framework

7.3. ACCESS_COARSE_LOCATION — It will determine the user location using Wifi and mobile data. It will give Approximated location
7.4. ACCESS_FINE_LOCATION- It will determine user location by using GPS. It will give you precious location.
7.5. We should the meta-data tag in application tag which contains API key value

Androidmanifest.xml file looks like below

<manifest xmlns:android=”http://schemas.android.com/apk/res/android"package=”com.example.drawroutes”><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” /><applicationandroid:allowBackup=”true”android:icon=”@mipmap/ic_launcher”android:label=”@string/app_name”android:roundIcon=”@mipmap/ic_launcher_round”android:supportsRtl=”true”android:theme=”@style/AppTheme”><meta-dataandroid: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>

8. Now we should change in build.gradle file

Here we should add the two dependencies. They are

  1. implementation ‘com.google.android.gms:play-services-maps:11.8.0’
  2. implementation ‘com.google.android.gms:play-services-location:11.8.0’

1st dependency is used to display the google map.

2nd dependency is used to get Google location and Activity recognition.

So build.gradle file looks like below

apply plugin: ‘com.android.application’android {compileSdkVersion 26defaultConfig {applicationId “com.example.drawroutes”minSdkVersion 19targetSdkVersion 26versionCode 1versionName “1.0”testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’}}}dependencies {implementation fileTree(dir: ‘libs’, include: [‘*.jar’])implementation ‘com.android.support:appcompat-v7:26.1.0’implementation ‘com.google.android.gms:play-services-maps:11.8.0’implementation ‘com.google.android.gms:play-services-location:11.8.0’}

9. Let’s start with MapsActivity, In this activity we should set the layout file named as
Activity_maps
10. In this xml file we should define a Fragment, here we should declare id and name for the fragment.

Finally xml as shown below.

<fragment xmlns:android=”http://schemas.android.com/apk/res/android"xmlns:tools=”http://schemas.android.com/tools"android:id=”@+id/map”android:name=”com.google.android.gms.maps.SupportMapFragment”android:layout_width=”match_parent”android:layout_height=”match_parent”tools:context=”com.example.drawroutes.MapsActivity” />

Here we are declaring android:name=”com.google.android.gms.maps.SupportMapFragment”

Because we are extending the activity from FragmentActivity.

If you want to use MapFragment then you can extend Activity.

11. Now MapsActivity should be extends FragmentActivity

Here we need to define the id like

Final SupportMapFragment mapFragment =(SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map);

Here we can divide the code and we will discuss about one by one.

So first we need to instantiate the GoogleMap class

12. Now we should declare map onClick Listner


mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
@Overridepublic void onMapClick(LatLng point) {// Already two locationsif (MarkerPoints.size() > 1) {MarkerPoints.clear();mMap.clear();}// Adding new item to the ArrayListMarkerPoints.add(point);// Creating MarkerOptionsMarkerOptions options = new MarkerOptions();// Setting the position of the markeroptions.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 V2mMap.addMarker(options);// Checks, whether start and end locations are capturedif (MarkerPoints.size() >= 2) {LatLng origin = MarkerPoints.get(0);LatLng dest = MarkerPoints.get(1);// Getting URL to the Google Directions APIString url = getUrl(origin, dest);Log.d(“onMapClick”, url.toString());FetchUrl FetchUrl = new FetchUrl();// Start downloading json data from Google Directions APIFetchUrl.execute(url);//move map cameramMap.moveCamera(CameraUpdateFactory.newLatLng(origin));mMap.animateCamera(CameraUpdateFactory.zoomTo(11));}}});

Above shown code will be executed when user tap on Android screen.
This is used to place the marker at the points between which path will be drawn.
MarkerPoints.get() is used to access and stored the Coordinates of tapped points.
It will be stored in LatLng origin and destination.
And getUrl is used to fetch the URL and it will be implemented using Async Task.

13. Async Task:
Async Task is an Abstract class which provided by Android, which helps to use UI thread.
Async Task class provide or allow us to perform long running operations or Background operations and the it shows the result on UI Thread without affecting Main Thread.
Async Task is used to run tasks/operations that need to be performed at background asynchronously.
In Async Task class there are two methods

13.1. doInbackground : Task will be implemented in this method
13.2. onPostExecute: Result will be shown in this method.

private class FetchUrl extends AsyncTask<String, Void, String> {@Overrideprotected String doInBackground(String… url) {// For storing data from web serviceString data = “”;try {// Fetching the data from web servicedata = downloadUrl(url[0]);Log.d(“Background Task data”, data.toString());} catch (Exception e) {Log.d(“Background Task”, e.toString());}return data;}@Overrideprotected void onPostExecute(String result) {super.onPostExecute(result);ParserTask parserTask = new ParserTask();// Invokes the thread for parsing the JSON dataparserTask.execute(result);}}

downloadUrl: This is used to fetch the URL from web service and its result will be parsed using ParserTask, it is also an Async Task.

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 urlurlConnection = (HttpURLConnection) url.openConnection();// Connecting to urlurlConnection.connect();// Reading data from urliStream = 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;}

Here data will be returned in the form of Json. which user can get using HttpURLConnection

15. Now Parser Task:
Define new class with the name ParserTask which extends AsyncTask. Here we should parse the Json data returned by downloadUrl method.

private class ParserTask extends AsyncTask<String, Integer, List<List<HashMap<String, String>>>> {// Parsing the data in non-ui thread@Overrideprotected 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 dataroutes = 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@Overrideprotected void onPostExecute(List<List<HashMap<String, String>>> result) {ArrayList<LatLng> points;PolylineOptions lineOptions = null;// Traversing through all the routesfor (int i = 0; i < result.size(); i++) {points = new ArrayList<>();lineOptions = new PolylineOptions();// Fetching i-th routeList<HashMap<String, String>> path = result.get(i);// Fetching all the points in i-th routefor (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 LineOptionslineOptions.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 routeif(lineOptions != null) {mMap.addPolyline(lineOptions);}else {Log.d(“onPostExecute”,”without Polylines drawn”);}}}

Here In doInBackround will parse the data.
In onPostExecute method we will add polyline to draw route on Google Map.
So we are parsing the data to another class i.e DataParser

16. DataParser.Java

class DataParser {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* */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;}}

Here Parse method we will get Json data here we can split JSONArray by using getJSONArray
And we should traverse the all routes, points ect. And all the traversing points we should add into list.
routes.add(path);

17. Now we should draw the route on Google map using polyline.
And that is done in onPostExecute Method in which ParseTask AsyncTask class.

@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”);
}
}

The above points fetched from result and drawn on Google maps.
Here ArrayList<LatLng> points is used to store the Latitude and Longitude positions on Google Map.
At last route is drawn on Google Map by using polyLine
lineOptions.addAll(points);

At last we should add the polyline to map like
mMap.addPolyline(lineOptions);

So finally we can run the application. It will run successfully. The output of the screen as shown below.

--

--