Here is the source code for routing between source and destination:
public class MapActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { private SupportMapFragment mapFragment; private GoogleMap map; private GoogleApiClient mGoogleApiClient; ArrayList markerPoints; private LocationRequest mLocationRequest; private long UPDATE_INTERVAL = 15000; /* 15 secs */ private long FASTEST_INTERVAL = 5000; /* 5 secs */ private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000; // Marker marker; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!isGooglePlayServicesAvailable()) { finish(); } setContentView(R.layout.activity_map); getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); getSupportActionBar().setDisplayShowCustomEnabled(true); getSupportActionBar().setCustomView(R.layout.custom_actionbar_maps); markerPoints = new ArrayList(); mapFragment = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)); if (mapFragment != null) { mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap map) { loadMap(map); } }); } else { Toast.makeText(this, "Error - Map Fragment was null!!", Toast.LENGTH_SHORT).show(); } } protected void loadMap(GoogleMap googleMap) { map = googleMap; if (map != null) { // Map is ready Toast.makeText(this, "Map Fragment was loaded properly!", Toast.LENGTH_SHORT).show(); map.setMyLocationEnabled(true); map.setOnMapClickListener(new GoogleMap.OnMapClickListener() { @Override public void onMapClick(LatLng point) { // Already two locations if(markerPoints.size()>1){ markerPoints.clear(); map.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 map.addMarker(options); // Checks, whether start and end locations are captured if(markerPoints.size() >= 2){ LatLng origin = (LatLng) markerPoints.get(0); LatLng dest = (LatLng) markerPoints.get(1); // Getting URL to the Google Directions API String url = getDirectionsUrl(origin, dest); DownloadTask downloadTask = new DownloadTask(); // Start downloading json data from Google Directions API downloadTask.execute(url); } } }); // Now that map has loaded, let get our location! mGoogleApiClient = new GoogleApiClient.Builder(this) .addApi(LocationServices.API) .addConnectionCallbacks(this) .addOnConnectionFailedListener(this).build(); connectClient(); } else { Toast.makeText(this, "Error - Map was null!!", Toast.LENGTH_SHORT).show(); } } protected void connectClient() { // Connect the client. if (isGooglePlayServicesAvailable() && mGoogleApiClient != null) { mGoogleApiClient.connect(); } } /* * Called when the Activity becomes visible. */ @Override protected void onStart() { super.onStart(); connectClient(); } /* * Called when the Activity is no longer visible. */ @Override protected void onStop() { // Disconnecting the client invalidates it. if (mGoogleApiClient != null) { mGoogleApiClient.disconnect(); } super.onStop(); } /* * Handle results returned to the FragmentActivity by Google Play services */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // Decide what to do based on the original request code switch (requestCode) { case CONNECTION_FAILURE_RESOLUTION_REQUEST: /* * If the result code is Activity.RESULT_OK, try to connect again */ switch (resultCode) { case Activity.RESULT_OK: mGoogleApiClient.connect(); break; } } } // Fetches data from url passed private boolean isGooglePlayServicesAvailable() { // Check that Google Play services is available int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this); // If Google Play services is available if (ConnectionResult.SUCCESS == resultCode) { // In debug mode, log the status Log.d("Location Updates", "Google Play services is available."); return true; } else { // Get the error dialog from Google Play services Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(resultCode, this, CONNECTION_FAILURE_RESOLUTION_REQUEST); // If Google Play services can provide an error dialog if (errorDialog != null) { // Create a new DialogFragment for the error dialog ErrorDialogFragment errorFragment = new ErrorDialogFragment(); errorFragment.setDialog(errorDialog); errorFragment.show(getSupportFragmentManager(), "Location Updates"); } return false; } } /* * Called by Location Services when the request to connect the client * finishes successfully. At this point, you can request the current * location or start periodic updates */ @Override public void onConnected(Bundle dataBundle) { // Display the connection status Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); if (location != null) { Toast.makeText(this, "GPS location was found!", Toast.LENGTH_SHORT).show(); LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16); map.animateCamera(cameraUpdate); //marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker)).flat(true).anchor(0.5f,0.5f)); startLocationUpdates(); } else { Toast.makeText(this, "Current location was null, enable GPS on emulator!", Toast.LENGTH_SHORT).show(); } } protected void startLocationUpdates() { mLocationRequest = new LocationRequest(); mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); mLocationRequest.setInterval(UPDATE_INTERVAL); mLocationRequest.setFastestInterval(FASTEST_INTERVAL); LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); } public void onLocationChanged(Location location) { // Report to the UI that the location was updated LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); /* if(marker == null){ *//* marker.remove();*//* marker = map.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.fromResource(R.drawable.vehicle_marker))); } marker.setPosition(latLng); */ CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 16); map.animateCamera(cameraUpdate); String msg = "Updated Location: " + Double.toString(location.getLatitude()) + "," + Double.toString(location.getLongitude()); Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } /* * Called by Location Services if the connection to the location client * drops because of an error. */ @Override public void onConnectionSuspended(int i) { if (i == CAUSE_SERVICE_DISCONNECTED) { Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show(); } else if (i == CAUSE_NETWORK_LOST) { Toast.makeText(this, "Network lost. Please re-connect.", Toast.LENGTH_SHORT).show(); } } /* * Called by Location Services if the attempt to Location Services fails. */ @Override public void onConnectionFailed(ConnectionResult connectionResult) { /* * Google Play services can resolve some errors it detects. If the error * has a resolution, try sending an Intent to start a Google Play * services activity that can resolve error. */ if (connectionResult.hasResolution()) { try { // Start an Activity that tries to resolve the error connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST); /* * Thrown if Google Play services canceled the original * PendingIntent */ } catch (IntentSender.SendIntentException e) { // Log the error e.printStackTrace(); } } else { Toast.makeText(getApplicationContext(), "Sorry. Location services not available to you", Toast.LENGTH_LONG).show(); } } // Define a DialogFragment that displays the error dialog public static class ErrorDialogFragment extends DialogFragment { // Global field to contain the error dialog private Dialog mDialog; // Default constructor. Sets the dialog field to null public ErrorDialogFragment() { super(); mDialog = null; } // Set the dialog to display public void setDialog(Dialog dialog) { mDialog = dialog; } // Return a Dialog to the DialogFragment. @Override public Dialog onCreateDialog(Bundle savedInstanceState) { return mDialog; } } // Fetches data from url passed private class DownloadTask extends AsyncTask<String, Void, String>{ // Downloading data in non-ui thread @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]); }catch(Exception e){ Log.d("Background Task",e.toString()); } return data; } // Executes in UI thread, after the execution of // doInBackground() @Override protected void onPostExecute(String result) { super.onPostExecute(result); ParserTask parserTask = new ParserTask(); // Invokes the thread for parsing the JSON data parserTask.execute(result); } } /** A class to parse the Google Places in JSON format */ 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]); DirectionsJSONParser parser = new DirectionsJSONParser(); // Starts parsing data routes = parser.parse(jObject); }catch(Exception e){ e.printStackTrace(); } return routes; } // Executes in UI thread, after the parsing process @Override protected void onPostExecute(List<List<HashMap<String, String>>> result) { ArrayList points = null; PolylineOptions lineOptions = null; MarkerOptions markerOptions = new MarkerOptions(); // 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(12); lineOptions.color(Color.RED); lineOptions.geodesic(true); } // Drawing polyline in the Google Map for the i-th route map.addPolyline(lineOptions); } } private String getDirectionsUrl(LatLng origin,LatLng dest){ // Origin of route String str_origin = "origin="+origin.latitude+","+origin.longitude; // Destination of route String str_dest = "destination="+dest.latitude+","+dest.longitude; // Sensor enabled String sensor = "sensor=false"; // Building the parameters to the web service String parameters = str_origin+"&"+str_dest+"&"+sensor; // Output format String output = "json"; // Building the url to the web service String url = "https://maps.googleapis.com/maps/api/directions/"+output+"?"+parameters; return url; } /** A method to download json data from url */ 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(); br.close(); }catch(Exception e){ Log.d("Exception while downloading url", e.toString()); }finally{ iStream.close(); urlConnection.disconnect(); } return data; } }
JSONParser.java directions are given below:
import com.google.android.gms.maps.model.LatLng; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class DirectionsJSONParser { public List<List<HashMap<String,String>>> parse(JSONObject jObject){ List<List<HashMap<String, String>>> routes = new ArrayList<List<HashMap<String,String>>>() ; JSONArray jRoutes = null; JSONArray jLegs = null; JSONArray jSteps = null; try { jRoutes = jObject.getJSONArray("routes"); for(int i=0;i<jRoutes.length();i++){ jLegs = ( (JSONObject)jRoutes.get(i)).getJSONArray("legs"); List path = new ArrayList<HashMap<String, String>>(); for(int j=0;j<jLegs.length();j++){ jSteps = ( (JSONObject)jLegs.get(j)).getJSONArray("steps"); for(int k=0;k<jSteps.length();k++){ String polyline = ""; polyline = (String)((JSONObject)((JSONObject)jSteps.get(k)).get("polyline")).get("points"); List list = decodePoly(polyline); for(int l=0;l <list.size();l++){ HashMap<String, String> hm = new HashMap<String, String>(); hm.put("lat", Double.toString(((LatLng)list.get(l)).latitude) ); hm.put("lng", Double.toString(((LatLng)list.get(l)).longitude) ); path.add(hm); } } routes.add(path); } } } catch (JSONException e) { e.printStackTrace(); }catch (Exception e){ } return routes; } private List decodePoly(String encoded) { List 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; } }